This patch enables the ZFS boot from zpool on a single whole disk for sparc64. Two new programs zfsboot and zfsloader are introduced. zfsboot is written to address [0x200, 0x2000) just like boot1, and is responsible to read zfsloader (one ELF program like loader) from 3.5MB ZFS Boot Block located at [0x80000, 0x400000). Known Limitations: 1. only zpool on a whole disk is supported, zfs boot from zpool in VTOC8 partitions may not work. 2. boot from mirror/raidz is not supported due to limited dev environment. Fix: generic steps: 1. build zfsboot and zfsloader 2. create zpool on your disk # zpool create tank /dev/<your disk, ie. ada0> 3. export the zpool # zpool export tank 4. install zfsboot # dd if=boot1 of=/dev/<your disk, ie. ada0> bs=512 skip=1 oseek=1 conv=notrunc 5. install zfsloader to ZFS Book Block location # dd if=zfsloader of=/dev/<your disk, ie. ada0> bs=512 oseek=1024 conv=notrunc 6. re-import your zpool to install FreeBSD files Patch attached with submission follows: How-To-Repeat: NA.
> Known Limitations: > 1. only zpool on a whole disk is supported, zfs boot from zpool in VTOC8 partitions may not work. Uhm, are you sure you didn't have (the remnants) of a VTOC label on the disk? I'd expect the firmware to refuse to boot from a disk not having one. > 2. boot from mirror/raidz is not supported due to limited dev environment. Could you also tackle these remaining bits or at least describe what it would take to support booting from a zpool in a VTOC label, mirror and raidz? > > >How-To-Repeat: > NA. > >Fix: > generic steps: > 1. build zfsboot and zfsloader > 2. create zpool on your disk > # zpool create tank /dev/<your disk, ie. ada0> > 3. export the zpool > # zpool export tank > 4. install zfsboot > # dd if=boot1 of=/dev/<your disk, ie. ada0> bs=512 skip=1 oseek=1 conv=notrunc Assuming there is a VTOC8 label, this could also be done using `gpart -b`, no? > 5. install zfsloader to ZFS Book Block location > # dd if=zfsloader of=/dev/<your disk, ie. ada0> bs=512 oseek=1024 conv=notrunc I think to vaguely remember there being a zfs command/way of writing a loader to that 3.5MB boot block area following the uberblock. Do you know what it is? In any case, nice work so far! Marius
>> Known Limitations: >> 1. only zpool on a whole disk is supported, zfs boot from zpool in VTOC8 partitions may not work. > > Uhm, are you sure you didn't have (the remnants) of a VTOC label on > the disk? I'd expect the firmware to refuse to boot from a disk not > having one. Sorry, it is my fault not writing this here. A fake VTOC8 label is still required, and it is not conflict with zpool on the whole disk, since ZFS reserved the first 8KB block unused. the VTOC8 table and boot1 (or zfsboot) code can be in this 8KB block. command `zpool create` will not destroy the VTOC8 table and the boot1 code. > >> 2. boot from mirror/raidz is not supported due to limited dev environment. > > Could you also tackle these remaining bits or at least describe what > it would take to support booting from a zpool in a VTOC label, mirror > and raidz? I do not have enough hardware to test booting from mirror/raidz disks, so I focus only on booting from one single disk in this PR. The default zfs_dev.dv_init() traverse all possible disks and slices/partitions to find all zpool vdev, I simply changed the behavior to read from one single disk only then it is easy to know which zpool should be used to boot (there will be only one). To support booting from mirror/raidz, all disks/slices must be traversed and it is needed to decide which zpool to boot. booting from a zpool in VTOC8 label should be possible for me to do dev/test, I need a little more VTOC8 knowledge and will try it later. > >> >> >How-To-Repeat: >> NA. >> >Fix: >> generic steps: >> 1. build zfsboot and zfsloader >> 2. create zpool on your disk >> # zpool create tank /dev/<your disk, ie. ada0> >> 3. export the zpool >> # zpool export tank >> 4. install zfsboot >> # dd if=boot1 of=/dev/<your disk, ie. ada0> bs=512 skip=1 oseek=1 conv=notrunc > > Assuming there is a VTOC8 label, this could also be done using `gpart -b`, > no? Yes, but I think we should keep the zpool exported, otherwise this command may fail. > >> 5. install zfsloader to ZFS Book Block location >> # dd if=zfsloader of=/dev/<your disk, ie. ada0> bs=512 oseek=1024 conv=notrunc > > I think to vaguely remember there being a zfs command/way of writing > a loader to that 3.5MB boot block area following the uberblock. Do > you know what it is? I am also finding this.:) without such command, it will not be able to update the zfsboot and zfsloader on the disk (dd will report error since zpool is being used). Maybe we need some other code changes. > > In any case, nice work so far! > > Marius > Cheers, Gavin Mu
Here is the updated patch to support zfs boot fully. Now boot from mirror/raidz pool are also supported. zfsboot is the enhancement of boot1. Instead of reading "/boot/loader" from UFS filesystem, it loads the ELF "zfsloader" program from the 3.5MB Boot Block of zpool in current vtoc8 partition (slice). zfsloader tries to probe the zpool in current vtoc8 partition and if it is valid, it records the guid, then search all disks to find all zpools in the vtoc8 partitions with freebsd-zfs tag. zfsloader uses devalias "disk<n>" to find the disks, so devalias must be defined for all your bootable disks by OBP (aka. {ok} mode). then it boots from the zpool with the same guid. If you use the whole disk as zpool, you can allocate all disk space into the first vtoc8 partition (for example, ada0a in FreeBSD) tag with freebsd-zfs to create zpool. It is same with creating zpool on the whole disk (ada0). For reading from multiple disks, some ofw code are changed. The former code does not work when reading from multiple disks and I am not sure if it is possible and how to do this. (I googled but did not find more useful things). So I changed the code to close the current disk before a new disk is opened, and there will be only one disk opened simultaneously. I am not sure if this will slow the disk reading for booting from raidz pool. (It is several minutes slow on my V100 machine to boot from raidz zpool). Steps to use zfs boot: 1. create vtoc8 # gpart create -s vtoc8 ada0 2. add partitions, for example # gpart add -t freebsd-swap -s 4g ada0 # gpart add -t freebsd-zfs ada0 the disk will be: # gpart show => 0 78156480 ada0 VTOC8 (37G) 0 8388480 1 freebsd-swap (4G) 8388480 69768000 2 freebsd-zfs (33G) 3. create zpool # zpool create tank ada0b or if you use mirrored/raidz type: # zpool create tank mirror ada0b ada1b # zpool create tank raidz ada0b ada1b ada2b.... 4. write boot1 # gpart bootcode -p /boot/boot1 -i 1 ada0 5. write zfsloader into ZFS Boot Block, currently there is no dedicate program to do this, so use dd instead. # dd if=./zfsloader of=/dev/ada0b bs=512 oseek=1024 conv=notrunc only one copy of boot1 and zfsloader is needed to boot even if you use mirror/raidz pool. surely you can write copies on each disk then you can boot from another disk when disk failure. 6. install system on the zpool... 7. now the system can be booted with: {1} ok boot disk0:b if you defined devalias {1} ok devalias disk0 disk0 /pci@1c,600000/ide@2/disk@0,0 If you use mirrored or raidz type of zpool, do not forget to define devalias for all used disks. The only flaw of this zfs boot support for sparc64 is the lack of a dedicate program to write zfsloader into ZFS Boot Block. Surely we still can use dd to do this simply. I do not think gpart is suitable to do such thing. Maybe it is reasonable to have a command like: # zpool installboot ./zfsloader tank But such a command will be used only by sparc64 architecture since other architectures does not use ZFS Boot Block. Cheers, Gavin Mu
On Mon, Feb 27, 2012 at 10:46:22PM +0800, Gavin Mu wrote: > Here is the updated patch to support zfs boot fully. Now boot from > mirror/raidz pool are also supported. > > zfsboot is the enhancement of boot1. Instead of reading "/boot/loader" > from UFS filesystem, it loads the ELF "zfsloader" program from the > 3.5MB Boot Block of zpool in current vtoc8 partition (slice). > > zfsloader tries to probe the zpool in current vtoc8 partition and if > it is valid, it records the guid, then search all disks to find all > zpools in the vtoc8 partitions with freebsd-zfs tag. zfsloader uses > devalias "disk<n>" to find the disks, so devalias must be defined for > all your bootable disks by OBP (aka. {ok} mode). then it boots from > the zpool with the same guid. > > If you use the whole disk as zpool, you can allocate all disk space > into the first vtoc8 partition (for example, ada0a in FreeBSD) tag > with freebsd-zfs to create zpool. It is same with creating zpool on > the whole disk (ada0). > > For reading from multiple disks, some ofw code are changed. The former > code does not work when reading from multiple disks and I am not sure > if it is possible and how to do this. (I googled but did not find more > useful things). So I changed the code to close the current disk before > a new disk is opened, and there will be only one disk opened > simultaneously. I am not sure if this will slow the disk reading for > booting from raidz pool. (It is several minutes slow on my V100 > machine to boot from raidz zpool). Typically, opening and closing devices via OFW causes quite a delay, the exact impact depends on the firmware version and the devices involved though. Therefore, it would be advisable to keep using the current approach of caching opened packages. In what way does this fail with ZFS? Basically, IEEE 1275 just says that support for opening a package more than once depends on the particular package but nothing about concurrently opening different packages. Not being able to concurrently open different packages also doesn't make all that much of a sense as opening one package also means to subsequentially open all the parents up to the root if not already opened and I think to actually have tested opening disks concurrently when writing the current code. Could this fail due to one device actually being opened twice, once via the full path and once via its alias? Marius
On Mon, Mar 5, 2012 at 2:06 AM, Marius Strobl <marius@alchemy.franken.de> wrote: > Typically, opening and closing devices via OFW causes quite a delay, > the exact impact depends on the firmware version and the devices > involved though. Therefore, it would be advisable to keep using the > current approach of caching opened packages. In what way does this > fail with ZFS? The error message on Fire V100 is: Fast Data Access MMU Miss > Basically, IEEE 1275 just says that support for > opening a package more than once depends on the particular package > but nothing about concurrently opening different packages. Not > being able to concurrently open different packages also doesn't > make all that much of a sense as opening one package also means > to subsequentially open all the parents up to the root if not > already opened and I think to actually have tested opening disks > concurrently when writing the current code. Could this fail due > to one device actually being opened twice, once via the full path > and once via its alias? There is no such scene though the code lacks the checking for full path/devalias. I have tried many times to find the root cause but I think it is difficult without open firmware knowledge. currently I found that following scenes will cause this issue with my test code: 1. do OF_seek(ihandle_t a) just after OF_close(ihandle_t b). in real world, OF_seek(a) is the step to read ZFS data just after OF_close() another disk during zfs init/probe. 2. do OF_seek(ihandle_t a) just after OF_open("available controller without disk"). For example there is no disk3 on my machine though there is disk controller. OF_open("disk3:") will report: Can't read disk label. Can't open disk label package in ofw_disk.c, OF_close() has been commented out for powerpc architecture, and can not find detail reason from code history, so I am thinking if we need also disable OF_close() for sparc64. for OF_open("normal disk controller without disk") issue, I did not find how to work around or fix yet. Is there any documents about how this open firmware work? I googled but can not find anything useful. Regards, Gavin Mu
On Thu, Apr 12, 2012 at 10:27:31PM +0800, Gavin Mu wrote: > On Mon, Mar 5, 2012 at 2:06 AM, Marius Strobl <marius@alchemy.franken.de> wrote: > > Typically, opening and closing devices via OFW causes quite a delay, > > the exact impact depends on the firmware version and the devices > > involved though. Therefore, it would be advisable to keep using the > > current approach of caching opened packages. In what way does this > > fail with ZFS? > The error message on Fire V100 is: Fast Data Access MMU Miss > > > Basically, IEEE 1275 just says that support for > > opening a package more than once depends on the particular package > > but nothing about concurrently opening different packages. Not > > being able to concurrently open different packages also doesn't > > make all that much of a sense as opening one package also means > > to subsequentially open all the parents up to the root if not > > already opened and I think to actually have tested opening disks > > concurrently when writing the current code. Could this fail due > > to one device actually being opened twice, once via the full path > > and once via its alias? > There is no such scene though the code lacks the checking for full > path/devalias. > I have tried many times to find the root cause but I think it is > difficult without open firmware knowledge. > currently I found that following scenes will cause this issue with my test code: > 1. do OF_seek(ihandle_t a) just after OF_close(ihandle_t b). in real > world, OF_seek(a) is the step to read ZFS data just after OF_close() > another disk during zfs init/probe. > 2. do OF_seek(ihandle_t a) just after OF_open("available controller > without disk"). For example there is no disk3 on my machine though > there is disk controller. OF_open("disk3:") will report: > Can't read disk label. > Can't open disk label package > > in ofw_disk.c, OF_close() has been commented out for powerpc > architecture, and can not find detail reason from code history, so I > am thinking if we need also disable OF_close() for sparc64. Hrm, some OFW implementations might have reference counting bugs, causing OF_close() to also close some parent(s) when these in fact are still used by another opened child device. Have you tried how it works when just commenting out the OF_close() in ofwd_close() but leaving the rest of ofw_disk.c as is? If that works, we probably can add a cleanup handler which closes all opened disk devices before leaving the loader, still taking advantage of caching opened disks. > > for OF_open("normal disk controller without disk") issue, I did not > find how to work around or fix yet. Currently, I can't think of a way to solve this with the available OFW interfaces. Have you checked whether OpenSolaris includes the source of the OFW ZFS loader bits and how it's done there or generally how a Solaris instalaltion handles this (f.e. does it create any additional aliases for ZFS providers and uses these instead etc)? > > Is there any documents about how this open firmware work? I googled > but can not find anything useful. > For the most part, there's just IEEE 1275. There once was a bit of related information on http://playground.sun.com/1275/, which unfortunately disappeared some time after Oracle took over. Marius
Author: marius Date: Sun Apr 29 15:54:40 2012 New Revision: 234789 URL: http://svn.freebsd.org/changeset/base/234789 Log: Add multiple inclusion protection. PR: 165025 Submitted by: Gavin Mu MFC after: 1 week Modified: head/sys/boot/common/bootstrap.h Modified: head/sys/boot/common/bootstrap.h ============================================================================== --- head/sys/boot/common/bootstrap.h Sun Apr 29 13:37:32 2012 (r234788) +++ head/sys/boot/common/bootstrap.h Sun Apr 29 15:54:40 2012 (r234789) @@ -26,6 +26,9 @@ * $FreeBSD$ */ +#ifndef _BOOTSTRAP_H_ +#define _BOOTSTRAP_H_ + #include <sys/types.h> #include <sys/queue.h> #include <sys/linker_set.h> @@ -323,3 +326,5 @@ void delay(int delay); void dev_cleanup(void); time_t time(time_t *tloc); + +#endif /* !_BOOTSTRAP_H_ */ _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
On Sun, Apr 22, 2012 at 08:40:13PM +0000, Marius Strobl wrote: > The following reply was made to PR sparc64/165025; it has been noted by GNATS. > > From: Marius Strobl <marius@alchemy.franken.de> > To: Gavin Mu <gavin.mu@gmail.com> > Cc: bug-followup@freebsd.org, Kurt Lidl <lidl@pix.net> > Subject: Re: sparc64/165025: [PATCH] zfsboot support for sparc64 > Date: Sun, 22 Apr 2012 22:32:11 +0200 > > On Thu, Apr 12, 2012 at 10:27:31PM +0800, Gavin Mu wrote: > > On Mon, Mar 5, 2012 at 2:06 AM, Marius Strobl <marius@alchemy.franken.de> wrote: > > > Typically, opening and closing devices via OFW causes quite a delay, > > > the exact impact depends on the firmware version and the devices > > > involved though. Therefore, it would be advisable to keep using the > > > current approach of caching opened packages. In what way does this > > > fail with ZFS? > > The error message on Fire V100 is: Fast Data Access MMU Miss > > > > > Basically, IEEE 1275 just says that support for > > > opening a package more than once depends on the particular package > > > but nothing about concurrently opening different packages. Not > > > being able to concurrently open different packages also doesn't > > > make all that much of a sense as opening one package also means > > > to subsequentially open all the parents up to the root if not > > > already opened and I think to actually have tested opening disks > > > concurrently when writing the current code. Could this fail due > > > to one device actually being opened twice, once via the full path > > > and once via its alias? > > There is no such scene though the code lacks the checking for full > > path/devalias. > > I have tried many times to find the root cause but I think it is > > difficult without open firmware knowledge. > > currently I found that following scenes will cause this issue with my test code: > > 1. do OF_seek(ihandle_t a) just after OF_close(ihandle_t b). in real > > world, OF_seek(a) is the step to read ZFS data just after OF_close() > > another disk during zfs init/probe. > > 2. do OF_seek(ihandle_t a) just after OF_open("available controller > > without disk"). For example there is no disk3 on my machine though > > there is disk controller. OF_open("disk3:") will report: > > Can't read disk label. > > Can't open disk label package > > > > in ofw_disk.c, OF_close() has been commented out for powerpc > > architecture, and can not find detail reason from code history, so I > > am thinking if we need also disable OF_close() for sparc64. > > Hrm, some OFW implementations might have reference counting bugs, > causing OF_close() to also close some parent(s) when these in fact > are still used by another opened child device. Have you tried how > it works when just commenting out the OF_close() in ofwd_close() but > leaving the rest of ofw_disk.c as is? If that works, we probably > can add a cleanup handler which closes all opened disk devices > before leaving the loader, still taking advantage of caching opened > disks. > With the machines I have at hand, I can't reproduce this problem, i.e. ofw_disk.c as is works just fine for booting from a mirror. This suggests that what you are seeing actually is a bug in the specific firmware implementation rather than a general limitation imposed by OFW. Could you please give the following patch a try? It implements what I've described above, i.e. combines both caching opened devices and properly closing all opened disks when leaving the loader. http://people.freebsd.org/~marius/ofw_disk_close_on_cleanup.diff Marius
On Mon, Apr 30, 2012 at 12:10 AM, Marius Strobl <marius@alchemy.franken.de> wrote: > On Sun, Apr 22, 2012 at 08:40:13PM +0000, Marius Strobl wrote: >> The following reply was made to PR sparc64/165025; it has been noted by = GNATS. >> >> From: Marius Strobl <marius@alchemy.franken.de> >> To: Gavin Mu <gavin.mu@gmail.com> >> Cc: bug-followup@freebsd.org, Kurt Lidl <lidl@pix.net> >> Subject: Re: sparc64/165025: [PATCH] zfsboot support for sparc64 >> Date: Sun, 22 Apr 2012 22:32:11 +0200 >> >> =A0On Thu, Apr 12, 2012 at 10:27:31PM +0800, Gavin Mu wrote: >> =A0> On Mon, Mar 5, 2012 at 2:06 AM, Marius Strobl <marius@alchemy.frank= en.de> wrote: >> =A0> > Typically, opening and closing devices via OFW causes quite a del= ay, >> =A0> > the exact impact depends on the firmware version and the devices >> =A0> > involved though. Therefore, it would be advisable to keep using t= he >> =A0> > current approach of caching opened packages. In what way does thi= s >> =A0> > fail with ZFS? >> =A0> The error message on Fire V100 is: Fast Data Access MMU Miss >> =A0> >> =A0> > Basically, IEEE 1275 just says that support for >> =A0> > opening a package more than once depends on the particular packag= e >> =A0> > but nothing about concurrently opening different packages. Not >> =A0> > being able to concurrently open different packages also doesn't >> =A0> > make all that much of a sense as opening one package also means >> =A0> > to subsequentially open all the parents up to the root if not >> =A0> > already opened and I think to actually have tested opening disks >> =A0> > concurrently when writing the current code. Could this fail due >> =A0> > to one device actually being opened twice, once via the full path >> =A0> > and once via its alias? >> =A0> There is no such scene though the code lacks the checking for full >> =A0> path/devalias. >> =A0> I have tried many times to find the root cause but I think it is >> =A0> difficult without open firmware knowledge. >> =A0> currently I found that following scenes will cause this issue with = my test code: >> =A0> 1. do OF_seek(ihandle_t a) just after OF_close(ihandle_t b). in rea= l >> =A0> world, OF_seek(a) is the step to read ZFS data just after OF_close(= ) >> =A0> another disk during zfs init/probe. >> =A0> 2. do OF_seek(ihandle_t a) just after OF_open("available controller >> =A0> without disk"). For example there is no disk3 on my machine though >> =A0> there is disk controller. OF_open("disk3:") will report: >> =A0> Can't read disk label. >> =A0> Can't open disk label package >> =A0> >> =A0> in ofw_disk.c, OF_close() has been commented out for powerpc >> =A0> architecture, and can not find detail reason from code history, so = I >> =A0> am thinking if we need also disable OF_close() for sparc64. >> >> =A0Hrm, some OFW implementations might have reference counting bugs, >> =A0causing OF_close() to also close some parent(s) when these in fact >> =A0are still used by another opened child device. Have you tried how >> =A0it works when just commenting out the OF_close() in ofwd_close() but >> =A0leaving the rest of ofw_disk.c as is? If that works, we probably >> =A0can add a cleanup handler which closes all opened disk devices >> =A0before leaving the loader, still taking advantage of caching opened >> =A0disks. >> > > With the machines I have at hand, I can't reproduce this problem, > i.e. ofw_disk.c as is works just fine for booting from a mirror. > This suggests that what you are seeing actually is a bug in the > specific firmware implementation rather than a general limitation > imposed by OFW. Could you please give the following patch a try? > It implements what I've described above, i.e. combines both caching > opened devices and properly closing all opened disks when leaving > the loader. > http://people.freebsd.org/~marius/ofw_disk_close_on_cleanup.diff > > Marius > I am sorry that I have lost the access to the sparc machines since I am moving to a new job. I checked your modification and there should be an issue of opening a slice twice, one by the real dev path and the other by devalias. ofw_disk can not deal with such scene. My testing machine is Sun Fire V100, a very old machine, and with the latest firmware (surely it is also very old though). I am not sure if we can still find same machine to do the testing. or can we call for some testers on several different hardware models before committing the code? Regards, Gavin Mu
Author: marius Date: Tue May 1 16:38:33 2012 New Revision: 234897 URL: http://svn.freebsd.org/changeset/base/234897 Log: Add a command for showing the heap usage. PR: 165025 Submitted by: Gavin Mu MFC after: 1 week Modified: head/sys/boot/sparc64/loader/main.c Modified: head/sys/boot/sparc64/loader/main.c ============================================================================== --- head/sys/boot/sparc64/loader/main.c Tue May 1 16:18:38 2012 (r234896) +++ head/sys/boot/sparc64/loader/main.c Tue May 1 16:38:33 2012 (r234897) @@ -800,6 +800,18 @@ main(int (*openfirm)(void *)) return (1); } +COMMAND_SET(heap, "heap", "show heap usage", command_heap); + +static int +command_heap(int argc, char *argv[]) +{ + + mallocstats(); + printf("heap base at %p, top at %p, upper limit at %p\n", heapva, + sbrk(0), heapva + HEAPSZ); + return(CMD_OK); +} + COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Tue May 1 17:16:01 2012 New Revision: 234898 URL: http://svn.freebsd.org/changeset/base/234898 Log: Add initial support for booting from ZFS on sparc64. At least on Sun Fire V100, the firmware is known to be broken and not allowing to simultaneously open disk devices, causing attempts to boot from a mirror or RAIDZ to cause a crash. This will be worked around later. The firmwares of newer sun4u models don't seem to exhibit this problem though. Steps for ZFS booting: 1. create VTOC8 label # gpart create -s vtoc8 da0 2. add partitions, f.e.: # gpart add -t freebsd-zfs -s 60g da0 # gpart add -t freebsd-swap da0 resulting in something like: # gpart show => 0 143331930 da0 VTOC8 (68G) 0 125821080 1 freebsd-zfs (60G) 125821080 17510850 2 freebsd-swap (8.4G) 3. create zpool # zpool create bunker da0a or for mirror/RAIDZ (after preparing additional disks as in steps 1. + 2.): # zpool create bunker mirror da0a da1a # zpool create bunker raidz da0a da1a da2a ... 4. set bootfs # zpool set bootfs=bunker bunker 5. install zfsboot # zpool export bunker # gpart bootcode -p /boot/zfsboot da0 6. write zfsloader to the ZFS Boot Block (so far, there's no dedicated tool for this, so dd(1) has to be used for this purpose) When using mirror/RAIDZ, step 4. and the dd(1) invocation should be repeated for the additional disks in order to be able to boot from another disk in case of failure. # sysctl kern.geom.debugflags=0x10 # dd if=/boot/zfsloader of=/dev/da0a bs=512 oseek=1024 conv=notrunc # zpool import bunker 7. install system on ZFS filesystem Don't forget to set 'zfs_load="YES"' and vfs.root.mountfrom="zfs:bunker" in loader.conf as well as 'zfs_enable="YES"'in rc.conf. 8. copy zpool.cache to the ZFS filesystem cp -p /boot/zfs/zpool.cache /bunker/boot/zfs/zpool.cache 9. set mountpoint # zfs set mountpoint=/ bunker 10. Now, given that aliases for all disks in the zpool exists (check with the `devalias` command on the boot monitor prompt) and disk0 corresponds to da0 (likewise for additional disks), the system can be booted from the ZFS with: {1} ok boot disk0 PR: 165025 Submitted by: Gavin Mu Added: head/sys/boot/sparc64/zfsboot/ head/sys/boot/sparc64/zfsboot/Makefile (contents, props changed) head/sys/boot/sparc64/zfsloader/ head/sys/boot/sparc64/zfsloader/Makefile (contents, props changed) Modified: head/sys/boot/ofw/libofw/devicename.c head/sys/boot/sparc64/Makefile head/sys/boot/sparc64/boot1/Makefile head/sys/boot/sparc64/boot1/boot1.c head/sys/boot/sparc64/loader/Makefile head/sys/boot/sparc64/loader/main.c head/sys/boot/zfs/zfs.c Modified: head/sys/boot/ofw/libofw/devicename.c ============================================================================== --- head/sys/boot/ofw/libofw/devicename.c Tue May 1 16:38:33 2012 (r234897) +++ head/sys/boot/ofw/libofw/devicename.c Tue May 1 17:16:01 2012 (r234898) @@ -28,6 +28,8 @@ __FBSDID("$FreeBSD$"); #include <stand.h> + +#include "bootstrap.h" #include "libofw.h" static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); @@ -76,6 +78,7 @@ ofw_parsedev(struct ofw_devdesc **dev, c phandle_t handle; const char *p; const char *s; + char *ep; char name[256]; char type[64]; int len; @@ -87,9 +90,10 @@ ofw_parsedev(struct ofw_devdesc **dev, c len = s - devspec; bcopy(devspec, name, len); name[len] = '\0'; - if ((handle = OF_finddevice(name)) == -1) - break; - if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) + if ((handle = OF_finddevice(name)) == -1) { + bcopy(name, type, len); + type[len] = '\0'; + } else if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) continue; for (i = 0; (dv = devsw[i]) != NULL; i++) { if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0) @@ -109,6 +113,18 @@ found: strcpy(idev->d_path, name); idev->d_dev = dv; idev->d_type = dv->dv_type; + if (idev->d_type == DEVT_ZFS) { + idev->d_unit = 0; + p = name + strlen(dv->dv_name); + if (*p && (*p != ':')) { + idev->d_unit = strtol(p, &ep, 0); + if (ep == p) { + free(idev); + return (EUNIT); + } + } + } + if (dev == NULL) { free(idev); } else { Modified: head/sys/boot/sparc64/Makefile ============================================================================== --- head/sys/boot/sparc64/Makefile Tue May 1 16:38:33 2012 (r234897) +++ head/sys/boot/sparc64/Makefile Tue May 1 17:16:01 2012 (r234898) @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= boot1 loader +SUBDIR= boot1 loader zfsboot zfsloader .include <bsd.subdir.mk> Modified: head/sys/boot/sparc64/boot1/Makefile ============================================================================== --- head/sys/boot/sparc64/boot1/Makefile Tue May 1 16:38:33 2012 (r234897) +++ head/sys/boot/sparc64/boot1/Makefile Tue May 1 17:16:01 2012 (r234898) @@ -3,22 +3,23 @@ PROG= boot1.elf INTERNALPROG= NO_MAN= -FILES= boot1 +FILES?= boot1 SRCS= _start.s boot1.c +CLEANFILES+=boot1 boot1.aout BOOTBLOCKBASE= 0x4000 -CFLAGS= -mcmodel=medlow -Os -I${.CURDIR}/../../common +CFLAGS+=-mcmodel=medlow -Os -I${.CURDIR}/../../common LDFLAGS=-Ttext ${BOOTBLOCKBASE} -Wl,-N # Construct boot1. sunlabel expects it to contain zeroed-out space for the # label, and to be of the correct size. boot1: boot1.aout + @set -- `ls -l boot1.aout`; x=$$((7680-$$5)); \ + echo "$$x bytes available"; test $$x -ge 0 dd if=/dev/zero of=${.TARGET} bs=512 count=16 dd if=boot1.aout of=${.TARGET} bs=512 oseek=1 conv=notrunc -CLEANFILES= boot1.aout - boot1.aout: boot1.elf elf2aout -o ${.TARGET} ${.ALLSRC} Modified: head/sys/boot/sparc64/boot1/boot1.c ============================================================================== --- head/sys/boot/sparc64/boot1/boot1.c Tue May 1 16:38:33 2012 (r234897) +++ head/sys/boot/sparc64/boot1/boot1.c Tue May 1 17:16:01 2012 (r234898) @@ -20,11 +20,13 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/dirent.h> + #include <machine/elf.h> #include <machine/stdarg.h> -#define _PATH_LOADER "/boot/loader" -#define _PATH_KERNEL "/boot/kernel/kernel" +#define _PATH_LOADER "/boot/loader" +#define _PATH_KERNEL "/boot/kernel/kernel" +#define READ_BUF_SIZE 8192 typedef int putc_func_t(char c, void *arg); typedef int32_t ofwh_t; @@ -45,17 +47,21 @@ static ofwh_t bootdev; static uint32_t fs_off; int main(int ac, char **av); - static void exit(int) __dead2; -static void load(const char *); -static int dskread(void *, u_int64_t, int); - static void usage(void); +#ifdef ZFSBOOT +static void loadzfs(void); +static int zbread(char *buf, off_t off, size_t bytes); +#else +static void load(const char *); +#endif + static void bcopy(const void *src, void *dst, size_t len); static void bzero(void *b, size_t len); static int mount(const char *device); +static int dskread(void *buf, u_int64_t lba, int nblk); static void panic(const char *fmt, ...) __dead2; static int printf(const char *fmt, ...); @@ -312,8 +318,6 @@ strcmp(const char *s1, const char *s2) return ((u_char)*s1 - (u_char)*s2); } -#include "ufsread.c" - int main(int ac, char **av) { @@ -335,14 +339,22 @@ main(int ac, char **av) } } - printf(" \n>> FreeBSD/sparc64 boot block\n" - " Boot path: %s\n" - " Boot loader: %s\n", bootpath, path); +#ifdef ZFSBOOT + printf(" \n>> FreeBSD/sparc64 ZFS boot block\n Boot path: %s\n", + bootpath); +#else + printf(" \n>> FreeBSD/sparc64 boot block\n Boot path: %s\n" + " Boot loader: %s\n", "", bootpath, path); +#endif if (mount(bootpath) == -1) panic("mount"); +#ifdef ZFSBOOT + loadzfs(); +#else load(path); +#endif return (1); } @@ -361,24 +373,86 @@ exit(int code) ofw_exit(); } -static struct dmadat __dmadat; +#ifdef ZFSBOOT + +#define VDEV_BOOT_OFFSET (2 * 256 * 1024) +static char zbuf[READ_BUF_SIZE]; static int -mount(const char *device) +zbread(char *buf, off_t off, size_t bytes) { + size_t len; + off_t poff; + off_t soff; + char *p; + unsigned int nb; + unsigned int lb; - dmadat = &__dmadat; - if ((bootdev = ofw_open(device)) == -1) { - printf("mount: can't open device\n"); - return (-1); + p = buf; + soff = VDEV_BOOT_OFFSET + off; + lb = (soff + bytes + DEV_BSIZE - 1) / DEV_BSIZE; + poff = soff; + while (poff < soff + bytes) { + nb = lb - poff / DEV_BSIZE; + if (nb > READ_BUF_SIZE / DEV_BSIZE) + nb = READ_BUF_SIZE / DEV_BSIZE; + if (dskread(zbuf, poff / DEV_BSIZE, nb)) + break; + if ((poff / DEV_BSIZE + nb) * DEV_BSIZE > soff + bytes) + len = soff + bytes - poff; + else + len = (poff / DEV_BSIZE + nb) * DEV_BSIZE - poff; + memcpy(p, zbuf + poff % DEV_BSIZE, len); + p += len; + poff += len; } - if (fsread(0, NULL, 0)) { - printf("mount: can't read superblock\n"); - return (-1); + return (poff - soff); +} + +static void +loadzfs(void) +{ + Elf64_Ehdr eh; + Elf64_Phdr ph; + caddr_t p; + ino_t ino; + int i; + + if (zbread((char *)&eh, 0, sizeof(eh)) != sizeof(eh)) { + printf("Can't read elf header\n"); + return; } - return (0); + if (!IS_ELF(eh)) { + printf("Not an ELF file\n"); + return; + } + for (i = 0; i < eh.e_phnum; i++) { + fs_off = eh.e_phoff + i * eh.e_phentsize; + if (zbread((char *)&ph, fs_off, sizeof(ph)) != sizeof(ph)) { + printf("Can't read program header %d\n", i); + return; + } + if (ph.p_type != PT_LOAD) + continue; + fs_off = ph.p_offset; + p = (caddr_t)ph.p_vaddr; + if (zbread(p, fs_off, ph.p_filesz) != ph.p_filesz) { + printf("Can't read content of section %d\n", i); + return; + } + if (ph.p_filesz != ph.p_memsz) + bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); + } + ofw_close(bootdev); + (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } +#else + +#include "ufsread.c" + +static struct dmadat __dmadat; + static void load(const char *fname) { @@ -421,6 +495,26 @@ load(const char *fname) (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } +#endif /* ZFSBOOT */ + +static int +mount(const char *device) +{ + + if ((bootdev = ofw_open(device)) == -1) { + printf("mount: can't open device\n"); + return (-1); + } +#ifndef ZFSBOOT + dmadat = &__dmadat; + if (fsread(0, NULL, 0)) { + printf("mount: can't read superblock\n"); + return (-1); + } +#endif + return (0); +} + static int dskread(void *buf, u_int64_t lba, int nblk) { Modified: head/sys/boot/sparc64/loader/Makefile ============================================================================== --- head/sys/boot/sparc64/loader/Makefile Tue May 1 16:38:33 2012 (r234897) +++ head/sys/boot/sparc64/loader/Makefile Tue May 1 17:16:01 2012 (r234898) @@ -3,8 +3,8 @@ .include <bsd.own.mk> MK_SSP= no -PROG= loader -NEWVERSWHAT= "bootstrap loader" sparc64 +PROG?= loader +NEWVERSWHAT?= "bootstrap loader" sparc64 INSTALLFLAGS= -b # Architecture-specific loader code @@ -13,12 +13,17 @@ SRCS= locore.S main.c metadata.c vers.c LOADER_DISK_SUPPORT?= yes LOADER_UFS_SUPPORT?= yes LOADER_CD9660_SUPPORT?= yes +LOADER_ZFS_SUPPORT?= no LOADER_NET_SUPPORT?= yes LOADER_NFS_SUPPORT?= yes LOADER_TFTP_SUPPORT?= yes LOADER_GZIP_SUPPORT?= yes LOADER_BZIP2_SUPPORT?= no +LOADER_DEBUG?= no +.if ${LOADER_DEBUG} == "yes" +CFLAGS+= -DLOADER_DEBUG +.endif .if ${LOADER_DISK_SUPPORT} == "yes" CFLAGS+= -DLOADER_DISK_SUPPORT .endif @@ -28,6 +33,11 @@ CFLAGS+= -DLOADER_UFS_SUPPORT .if ${LOADER_CD9660_SUPPORT} == "yes" CFLAGS+= -DLOADER_CD9660_SUPPORT .endif +.if ${LOADER_ZFS_SUPPORT} == "yes" +CFLAGS+= -DLOADER_ZFS_SUPPORT +CFLAGS+= -I${.CURDIR}/../../zfs +CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs +.endif .if ${LOADER_GZIP_SUPPORT} == "yes" CFLAGS+= -DLOADER_GZIP_SUPPORT .endif @@ -47,7 +57,8 @@ CFLAGS+= -DLOADER_TFTP_SUPPORT .if ${MK_FORTH} != "no" # Enable BootForth BOOT_FORTH= yes -CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/sparc64 +CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl +CFLAGS+= -I${.CURDIR}/../../ficl/sparc64 LIBFICL= ${.OBJDIR}/../../ficl/libficl.a .endif @@ -75,8 +86,9 @@ CFLAGS+= -I${.CURDIR}/../../../../lib/li DPADD= ${LIBFICL} ${LIBOFW} ${LIBSTAND} LDADD= ${LIBFICL} ${LIBOFW} -lstand -vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version - sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} +vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version + sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version \ + ${NEWVERSWHAT} loader.help: help.common help.sparc64 cat ${.ALLSRC} | \ Modified: head/sys/boot/sparc64/loader/main.c ============================================================================== --- head/sys/boot/sparc64/loader/main.c Tue May 1 16:38:33 2012 (r234897) +++ head/sys/boot/sparc64/loader/main.c Tue May 1 17:16:01 2012 (r234898) @@ -51,6 +51,9 @@ __FBSDID("$FreeBSD$"); #include <sys/linker.h> #include <sys/queue.h> #include <sys/types.h> +#ifdef LOADER_ZFS_SUPPORT +#include <sys/vtoc.h> +#endif #include <vm/vm.h> #include <machine/asi.h> @@ -143,6 +146,11 @@ static vm_offset_t heapva; static phandle_t root; +#ifdef LOADER_ZFS_SUPPORT +static int zfs_dev_init(void); +#include "zfs.c" +#endif + /* * Machine dependent structures that the machine independent * loader part uses. @@ -154,6 +162,9 @@ struct devsw *devsw[] = { #ifdef LOADER_NET_SUPPORT &netdev, #endif +#ifdef LOADER_ZFS_SUPPORT + &zfs_dev, +#endif 0 }; struct arch_switch archsw; @@ -166,6 +177,7 @@ struct file_format *file_formats[] = { &sparc64_elf, 0 }; + struct fs_ops *file_system[] = { #ifdef LOADER_UFS_SUPPORT &ufs_fsops, @@ -173,6 +185,9 @@ struct fs_ops *file_system[] = { #ifdef LOADER_CD9660_SUPPORT &cd9660_fsops, #endif +#ifdef LOADER_ZFS_SUPPORT + &zfs_fsops, +#endif #ifdef LOADER_ZIP_SUPPORT &zipfs_fsops, #endif @@ -721,6 +736,82 @@ tlb_init_sun4u(void) panic("%s: can't allocate TLB store", __func__); } +#ifdef LOADER_ZFS_SUPPORT + +static int +zfs_dev_init(void) +{ + struct vtoc8 vtoc; + char devname[512]; + spa_t *spa; + vdev_t *vdev; + uint64_t guid; + int fd, part, unit; + + zfs_init(); + + guid = 0; + /* Get the GUID of the ZFS pool on the boot device. */ + fd = open(getenv("currdev"), O_RDONLY); + if (fd != -1) { + if (vdev_probe(vdev_read, (void *)(uintptr_t) fd, &spa) == 0) + guid = spa->spa_guid; + close(fd); + } + + /* Clean up the environment to let ZFS work. */ + while ((vdev = STAILQ_FIRST(&zfs_vdevs)) != NULL) { + STAILQ_REMOVE_HEAD(&zfs_vdevs, v_alllink); + free(vdev); + } + while ((spa = STAILQ_FIRST(&zfs_pools)) != NULL) { + STAILQ_REMOVE_HEAD(&zfs_pools, spa_link); + free(spa); + } + + for (unit = 0; unit < MAXBDDEV; unit++) { + /* Find freebsd-zfs slices in the VTOC. */ + sprintf(devname, "disk%d:", unit); + fd = open(devname, O_RDONLY); + if (fd == -1) + continue; + lseek(fd, 0, SEEK_SET); + if (read(fd, &vtoc, sizeof(vtoc)) != sizeof(vtoc)) { + close(fd); + continue; + } + close(fd); + + for (part = 0; part < 8; part++) { + if (part == 2 || vtoc.part[part].tag != + VTOC_TAG_FREEBSD_ZFS) + continue; + sprintf(devname, "disk%d:%c", unit, part + 'a'); + fd = open(devname, O_RDONLY); + if (fd == -1) + break; + + if (vdev_probe(vdev_read, (void*)(uintptr_t) fd, 0)) + close(fd); + } + } + + if (guid != 0) { + unit = zfs_guid_to_unit(guid); + if (unit >= 0) { + /* Update the environment for ZFS. */ + sprintf(devname, "zfs%d", unit); + env_setenv("currdev", EV_VOLATILE, devname, + ofw_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, devname, + env_noset, env_nounset); + } + } + return (0); +} + +#endif /* LOADER_ZFS_SUPPORT */ + int main(int (*openfirm)(void *)) { @@ -756,14 +847,6 @@ main(int (*openfirm)(void *)) mmu_ops->tlb_init(); /* - * Initialize devices. - */ - for (dp = devsw; *dp != 0; dp++) { - if ((*dp)->dv_init != 0) - (*dp)->dv_init(); - } - - /* * Set up the current device. */ OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)); @@ -780,7 +863,8 @@ main(int (*openfirm)(void *)) * needs to be altered. */ if (bootpath[strlen(bootpath) - 2] == ':' && - bootpath[strlen(bootpath) - 1] == 'f') { + bootpath[strlen(bootpath) - 1] == 'f' && + strstr(bootpath, "cdrom")) { bootpath[strlen(bootpath) - 1] = 'a'; printf("Boot path set to %s\n", bootpath); } @@ -790,6 +874,13 @@ main(int (*openfirm)(void *)) env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset, env_nounset); + /* + * Initialize devices. + */ + for (dp = devsw; *dp != 0; dp++) + if ((*dp)->dv_init != 0) + (*dp)->dv_init(); + printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); Added: head/sys/boot/sparc64/zfsboot/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/sparc64/zfsboot/Makefile Tue May 1 17:16:01 2012 (r234898) @@ -0,0 +1,13 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../boot1 + +PROGNAME= zfsboot +CFLAGS+= -DZFSBOOT +FILES= zfsboot +CLEANFILES+= zfsboot + +zfsboot: boot1 + ln -s ${.ALLSRC} ${.TARGET} + +.include "${.CURDIR}/../boot1/Makefile" Added: head/sys/boot/sparc64/zfsloader/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/sparc64/zfsloader/Makefile Tue May 1 17:16:01 2012 (r234898) @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../loader + +PROG= zfsloader +NEWVERSWHAT= "ZFS enabled bootstrap loader" sparc64 +LOADER_ZFS_SUPPORT=yes + +.include "${.CURDIR}/../loader/Makefile" Modified: head/sys/boot/zfs/zfs.c ============================================================================== --- head/sys/boot/zfs/zfs.c Tue May 1 16:38:33 2012 (r234897) +++ head/sys/boot/zfs/zfs.c Tue May 1 17:16:01 2012 (r234898) @@ -399,6 +399,7 @@ zfs_guid_to_unit(uint64_t guid) return (-1); } +#if defined(__amd64__) || defined(__i386__) static int zfs_dev_init(void) { @@ -441,6 +442,7 @@ zfs_dev_init(void) return (0); } +#endif /* * Print information about ZFS pools _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Fri May 25 14:54:12 2012 New Revision: 235995 URL: http://svn.freebsd.org/changeset/base/235995 Log: MFC: r234789 Add multiple inclusion protection. PR: 165025 Submitted by: Gavin Mu Modified: stable/9/sys/boot/common/bootstrap.h Directory Properties: stable/9/sys/ (props changed) stable/9/sys/amd64/include/xen/ (props changed) stable/9/sys/boot/ (props changed) stable/9/sys/boot/i386/efi/ (props changed) stable/9/sys/boot/ia64/efi/ (props changed) stable/9/sys/boot/ia64/ski/ (props changed) stable/9/sys/boot/powerpc/boot1.chrp/ (props changed) stable/9/sys/boot/powerpc/ofw/ (props changed) stable/9/sys/cddl/contrib/opensolaris/ (props changed) stable/9/sys/conf/ (props changed) stable/9/sys/contrib/dev/acpica/ (props changed) stable/9/sys/contrib/octeon-sdk/ (props changed) stable/9/sys/contrib/pf/ (props changed) stable/9/sys/contrib/x86emu/ (props changed) stable/9/sys/dev/ (props changed) stable/9/sys/dev/e1000/ (props changed) stable/9/sys/dev/ixgbe/ (props changed) stable/9/sys/fs/ (props changed) stable/9/sys/fs/ntfs/ (props changed) stable/9/sys/modules/ (props changed) Modified: stable/9/sys/boot/common/bootstrap.h ============================================================================== --- stable/9/sys/boot/common/bootstrap.h Fri May 25 14:52:05 2012 (r235994) +++ stable/9/sys/boot/common/bootstrap.h Fri May 25 14:54:12 2012 (r235995) @@ -26,6 +26,9 @@ * $FreeBSD$ */ +#ifndef _BOOTSTRAP_H_ +#define _BOOTSTRAP_H_ + #include <sys/types.h> #include <sys/queue.h> #include <sys/linker_set.h> @@ -323,3 +326,5 @@ void delay(int delay); void dev_cleanup(void); time_t time(time_t *tloc); + +#endif /* !_BOOTSTRAP_H_ */ _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Fri May 25 14:54:18 2012 New Revision: 235996 URL: http://svn.freebsd.org/changeset/base/235996 Log: MFC: r234789 Add multiple inclusion protection. PR: 165025 Submitted by: Gavin Mu Modified: stable/8/sys/boot/common/bootstrap.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/boot/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/e1000/ (props changed) Modified: stable/8/sys/boot/common/bootstrap.h ============================================================================== --- stable/8/sys/boot/common/bootstrap.h Fri May 25 14:54:12 2012 (r235995) +++ stable/8/sys/boot/common/bootstrap.h Fri May 25 14:54:18 2012 (r235996) @@ -26,6 +26,9 @@ * $FreeBSD$ */ +#ifndef _BOOTSTRAP_H_ +#define _BOOTSTRAP_H_ + #include <sys/types.h> #include <sys/queue.h> #include <sys/linker_set.h> @@ -307,3 +310,5 @@ void delay(int delay); void dev_cleanup(void); time_t time(time_t *tloc); + +#endif /* !_BOOTSTRAP_H_ */ _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Fri May 25 14:57:01 2012 New Revision: 235997 URL: http://svn.freebsd.org/changeset/base/235997 Log: MFC: r234897 Add a command for showing the heap usage. PR: 165025 Submitted by: Gavin Mu Modified: stable/9/sys/boot/sparc64/loader/main.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/amd64/include/xen/ (props changed) stable/9/sys/boot/ (props changed) stable/9/sys/boot/i386/efi/ (props changed) stable/9/sys/boot/ia64/efi/ (props changed) stable/9/sys/boot/ia64/ski/ (props changed) stable/9/sys/boot/powerpc/boot1.chrp/ (props changed) stable/9/sys/boot/powerpc/ofw/ (props changed) stable/9/sys/cddl/contrib/opensolaris/ (props changed) stable/9/sys/conf/ (props changed) stable/9/sys/contrib/dev/acpica/ (props changed) stable/9/sys/contrib/octeon-sdk/ (props changed) stable/9/sys/contrib/pf/ (props changed) stable/9/sys/contrib/x86emu/ (props changed) stable/9/sys/dev/ (props changed) stable/9/sys/dev/e1000/ (props changed) stable/9/sys/dev/ixgbe/ (props changed) stable/9/sys/fs/ (props changed) stable/9/sys/fs/ntfs/ (props changed) stable/9/sys/modules/ (props changed) Modified: stable/9/sys/boot/sparc64/loader/main.c ============================================================================== --- stable/9/sys/boot/sparc64/loader/main.c Fri May 25 14:54:18 2012 (r235996) +++ stable/9/sys/boot/sparc64/loader/main.c Fri May 25 14:57:01 2012 (r235997) @@ -800,6 +800,18 @@ main(int (*openfirm)(void *)) return (1); } +COMMAND_SET(heap, "heap", "show heap usage", command_heap); + +static int +command_heap(int argc, char *argv[]) +{ + + mallocstats(); + printf("heap base at %p, top at %p, upper limit at %p\n", heapva, + sbrk(0), heapva + HEAPSZ); + return(CMD_OK); +} + COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Fri May 25 14:57:02 2012 New Revision: 235998 URL: http://svn.freebsd.org/changeset/base/235998 Log: MFC: r234897 Add a command for showing the heap usage. PR: 165025 Submitted by: Gavin Mu Modified: stable/8/sys/boot/sparc64/loader/main.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/boot/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/e1000/ (props changed) Modified: stable/8/sys/boot/sparc64/loader/main.c ============================================================================== --- stable/8/sys/boot/sparc64/loader/main.c Fri May 25 14:57:01 2012 (r235997) +++ stable/8/sys/boot/sparc64/loader/main.c Fri May 25 14:57:02 2012 (r235998) @@ -915,6 +915,18 @@ main(int (*openfirm)(void *)) return (1); } +COMMAND_SET(heap, "heap", "show heap usage", command_heap); + +static int +command_heap(int argc, char *argv[]) +{ + + mallocstats(); + printf("heap base at %p, top at %p, upper limit at %p\n", heapva, + sbrk(0), heapva + HEAPSZ); + return(CMD_OK); +} + COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Sat May 26 08:54:26 2012 New Revision: 236076 URL: http://svn.freebsd.org/changeset/base/236076 Log: MFC: r234898, r235207 Add initial support for booting from ZFS on sparc64. At least on Sun Fire V100, the firmware is known to be broken and not allowing to simultaneously open disk devices, causing attempts to boot from a mirror or RAIDZ to cause a crash. This will be worked around later. The firmwares of newer sun4u models don't seem to exhibit this problem though. PR: 165025 Submitted by: Gavin Mu Added: stable/9/sys/boot/sparc64/zfsboot/ - copied from r234898, head/sys/boot/sparc64/zfsboot/ stable/9/sys/boot/sparc64/zfsloader/ - copied from r234898, head/sys/boot/sparc64/zfsloader/ Modified: stable/9/sys/boot/ofw/libofw/devicename.c stable/9/sys/boot/sparc64/Makefile stable/9/sys/boot/sparc64/boot1/Makefile stable/9/sys/boot/sparc64/boot1/boot1.c stable/9/sys/boot/sparc64/loader/Makefile stable/9/sys/boot/sparc64/loader/main.c stable/9/sys/boot/sparc64/zfsboot/Makefile stable/9/sys/boot/zfs/zfs.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/amd64/include/xen/ (props changed) stable/9/sys/boot/ (props changed) stable/9/sys/boot/i386/efi/ (props changed) stable/9/sys/boot/ia64/efi/ (props changed) stable/9/sys/boot/ia64/ski/ (props changed) stable/9/sys/boot/powerpc/boot1.chrp/ (props changed) stable/9/sys/boot/powerpc/ofw/ (props changed) stable/9/sys/cddl/contrib/opensolaris/ (props changed) stable/9/sys/conf/ (props changed) stable/9/sys/contrib/dev/acpica/ (props changed) stable/9/sys/contrib/octeon-sdk/ (props changed) stable/9/sys/contrib/pf/ (props changed) stable/9/sys/contrib/x86emu/ (props changed) stable/9/sys/dev/ (props changed) stable/9/sys/dev/e1000/ (props changed) stable/9/sys/dev/ixgbe/ (props changed) stable/9/sys/fs/ (props changed) stable/9/sys/fs/ntfs/ (props changed) stable/9/sys/modules/ (props changed) Modified: stable/9/sys/boot/ofw/libofw/devicename.c ============================================================================== --- stable/9/sys/boot/ofw/libofw/devicename.c Sat May 26 08:44:50 2012 (r236075) +++ stable/9/sys/boot/ofw/libofw/devicename.c Sat May 26 08:54:26 2012 (r236076) @@ -28,6 +28,8 @@ __FBSDID("$FreeBSD$"); #include <stand.h> + +#include "bootstrap.h" #include "libofw.h" static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); @@ -76,6 +78,7 @@ ofw_parsedev(struct ofw_devdesc **dev, c phandle_t handle; const char *p; const char *s; + char *ep; char name[256]; char type[64]; int len; @@ -87,9 +90,10 @@ ofw_parsedev(struct ofw_devdesc **dev, c len = s - devspec; bcopy(devspec, name, len); name[len] = '\0'; - if ((handle = OF_finddevice(name)) == -1) - break; - if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) + if ((handle = OF_finddevice(name)) == -1) { + bcopy(name, type, len); + type[len] = '\0'; + } else if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) continue; for (i = 0; (dv = devsw[i]) != NULL; i++) { if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0) @@ -109,6 +113,18 @@ found: strcpy(idev->d_path, name); idev->d_dev = dv; idev->d_type = dv->dv_type; + if (idev->d_type == DEVT_ZFS) { + idev->d_unit = 0; + p = name + strlen(dv->dv_name); + if (*p && (*p != ':')) { + idev->d_unit = strtol(p, &ep, 0); + if (ep == p) { + free(idev); + return (EUNIT); + } + } + } + if (dev == NULL) { free(idev); } else { Modified: stable/9/sys/boot/sparc64/Makefile ============================================================================== --- stable/9/sys/boot/sparc64/Makefile Sat May 26 08:44:50 2012 (r236075) +++ stable/9/sys/boot/sparc64/Makefile Sat May 26 08:54:26 2012 (r236076) @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= boot1 loader +SUBDIR= boot1 loader zfsboot zfsloader .include <bsd.subdir.mk> Modified: stable/9/sys/boot/sparc64/boot1/Makefile ============================================================================== --- stable/9/sys/boot/sparc64/boot1/Makefile Sat May 26 08:44:50 2012 (r236075) +++ stable/9/sys/boot/sparc64/boot1/Makefile Sat May 26 08:54:26 2012 (r236076) @@ -3,22 +3,23 @@ PROG= boot1.elf INTERNALPROG= NO_MAN= -FILES= boot1 +FILES?= boot1 SRCS= _start.s boot1.c +CLEANFILES=${FILES} boot1.aout BOOTBLOCKBASE= 0x4000 -CFLAGS= -mcmodel=medlow -Os -I${.CURDIR}/../../common +CFLAGS+=-mcmodel=medlow -Os -I${.CURDIR}/../../common LDFLAGS=-Ttext ${BOOTBLOCKBASE} -Wl,-N # Construct boot1. sunlabel expects it to contain zeroed-out space for the # label, and to be of the correct size. -boot1: boot1.aout +${FILES}: boot1.aout + @set -- `ls -l boot1.aout`; x=$$((7680-$$5)); \ + echo "$$x bytes available"; test $$x -ge 0 dd if=/dev/zero of=${.TARGET} bs=512 count=16 dd if=boot1.aout of=${.TARGET} bs=512 oseek=1 conv=notrunc -CLEANFILES= boot1.aout - boot1.aout: boot1.elf elf2aout -o ${.TARGET} ${.ALLSRC} Modified: stable/9/sys/boot/sparc64/boot1/boot1.c ============================================================================== --- stable/9/sys/boot/sparc64/boot1/boot1.c Sat May 26 08:44:50 2012 (r236075) +++ stable/9/sys/boot/sparc64/boot1/boot1.c Sat May 26 08:54:26 2012 (r236076) @@ -20,11 +20,13 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/dirent.h> + #include <machine/elf.h> #include <machine/stdarg.h> -#define _PATH_LOADER "/boot/loader" -#define _PATH_KERNEL "/boot/kernel/kernel" +#define _PATH_LOADER "/boot/loader" +#define _PATH_KERNEL "/boot/kernel/kernel" +#define READ_BUF_SIZE 8192 typedef int putc_func_t(char c, void *arg); typedef int32_t ofwh_t; @@ -45,17 +47,21 @@ static ofwh_t bootdev; static uint32_t fs_off; int main(int ac, char **av); - static void exit(int) __dead2; -static void load(const char *); -static int dskread(void *, u_int64_t, int); - static void usage(void); +#ifdef ZFSBOOT +static void loadzfs(void); +static int zbread(char *buf, off_t off, size_t bytes); +#else +static void load(const char *); +#endif + static void bcopy(const void *src, void *dst, size_t len); static void bzero(void *b, size_t len); static int mount(const char *device); +static int dskread(void *buf, u_int64_t lba, int nblk); static void panic(const char *fmt, ...) __dead2; static int printf(const char *fmt, ...); @@ -312,8 +318,6 @@ strcmp(const char *s1, const char *s2) return ((u_char)*s1 - (u_char)*s2); } -#include "ufsread.c" - int main(int ac, char **av) { @@ -335,14 +339,22 @@ main(int ac, char **av) } } - printf(" \n>> FreeBSD/sparc64 boot block\n" - " Boot path: %s\n" - " Boot loader: %s\n", bootpath, path); +#ifdef ZFSBOOT + printf(" \n>> FreeBSD/sparc64 ZFS boot block\n Boot path: %s\n", + bootpath); +#else + printf(" \n>> FreeBSD/sparc64 boot block\n Boot path: %s\n" + " Boot loader: %s\n", "", bootpath, path); +#endif if (mount(bootpath) == -1) panic("mount"); +#ifdef ZFSBOOT + loadzfs(); +#else load(path); +#endif return (1); } @@ -361,24 +373,86 @@ exit(int code) ofw_exit(); } -static struct dmadat __dmadat; +#ifdef ZFSBOOT + +#define VDEV_BOOT_OFFSET (2 * 256 * 1024) +static char zbuf[READ_BUF_SIZE]; static int -mount(const char *device) +zbread(char *buf, off_t off, size_t bytes) { + size_t len; + off_t poff; + off_t soff; + char *p; + unsigned int nb; + unsigned int lb; - dmadat = &__dmadat; - if ((bootdev = ofw_open(device)) == -1) { - printf("mount: can't open device\n"); - return (-1); + p = buf; + soff = VDEV_BOOT_OFFSET + off; + lb = (soff + bytes + DEV_BSIZE - 1) / DEV_BSIZE; + poff = soff; + while (poff < soff + bytes) { + nb = lb - poff / DEV_BSIZE; + if (nb > READ_BUF_SIZE / DEV_BSIZE) + nb = READ_BUF_SIZE / DEV_BSIZE; + if (dskread(zbuf, poff / DEV_BSIZE, nb)) + break; + if ((poff / DEV_BSIZE + nb) * DEV_BSIZE > soff + bytes) + len = soff + bytes - poff; + else + len = (poff / DEV_BSIZE + nb) * DEV_BSIZE - poff; + memcpy(p, zbuf + poff % DEV_BSIZE, len); + p += len; + poff += len; } - if (fsread(0, NULL, 0)) { - printf("mount: can't read superblock\n"); - return (-1); + return (poff - soff); +} + +static void +loadzfs(void) +{ + Elf64_Ehdr eh; + Elf64_Phdr ph; + caddr_t p; + ino_t ino; + int i; + + if (zbread((char *)&eh, 0, sizeof(eh)) != sizeof(eh)) { + printf("Can't read elf header\n"); + return; } - return (0); + if (!IS_ELF(eh)) { + printf("Not an ELF file\n"); + return; + } + for (i = 0; i < eh.e_phnum; i++) { + fs_off = eh.e_phoff + i * eh.e_phentsize; + if (zbread((char *)&ph, fs_off, sizeof(ph)) != sizeof(ph)) { + printf("Can't read program header %d\n", i); + return; + } + if (ph.p_type != PT_LOAD) + continue; + fs_off = ph.p_offset; + p = (caddr_t)ph.p_vaddr; + if (zbread(p, fs_off, ph.p_filesz) != ph.p_filesz) { + printf("Can't read content of section %d\n", i); + return; + } + if (ph.p_filesz != ph.p_memsz) + bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); + } + ofw_close(bootdev); + (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } +#else + +#include "ufsread.c" + +static struct dmadat __dmadat; + static void load(const char *fname) { @@ -421,6 +495,26 @@ load(const char *fname) (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } +#endif /* ZFSBOOT */ + +static int +mount(const char *device) +{ + + if ((bootdev = ofw_open(device)) == -1) { + printf("mount: can't open device\n"); + return (-1); + } +#ifndef ZFSBOOT + dmadat = &__dmadat; + if (fsread(0, NULL, 0)) { + printf("mount: can't read superblock\n"); + return (-1); + } +#endif + return (0); +} + static int dskread(void *buf, u_int64_t lba, int nblk) { Modified: stable/9/sys/boot/sparc64/loader/Makefile ============================================================================== --- stable/9/sys/boot/sparc64/loader/Makefile Sat May 26 08:44:50 2012 (r236075) +++ stable/9/sys/boot/sparc64/loader/Makefile Sat May 26 08:54:26 2012 (r236076) @@ -3,8 +3,8 @@ .include <bsd.own.mk> MK_SSP= no -PROG= loader -NEWVERSWHAT= "bootstrap loader" sparc64 +PROG?= loader +NEWVERSWHAT?= "bootstrap loader" sparc64 INSTALLFLAGS= -b # Architecture-specific loader code @@ -13,12 +13,17 @@ SRCS= locore.S main.c metadata.c vers.c LOADER_DISK_SUPPORT?= yes LOADER_UFS_SUPPORT?= yes LOADER_CD9660_SUPPORT?= yes +LOADER_ZFS_SUPPORT?= no LOADER_NET_SUPPORT?= yes LOADER_NFS_SUPPORT?= yes LOADER_TFTP_SUPPORT?= yes LOADER_GZIP_SUPPORT?= yes LOADER_BZIP2_SUPPORT?= no +LOADER_DEBUG?= no +.if ${LOADER_DEBUG} == "yes" +CFLAGS+= -DLOADER_DEBUG +.endif .if ${LOADER_DISK_SUPPORT} == "yes" CFLAGS+= -DLOADER_DISK_SUPPORT .endif @@ -28,6 +33,11 @@ CFLAGS+= -DLOADER_UFS_SUPPORT .if ${LOADER_CD9660_SUPPORT} == "yes" CFLAGS+= -DLOADER_CD9660_SUPPORT .endif +.if ${LOADER_ZFS_SUPPORT} == "yes" +CFLAGS+= -DLOADER_ZFS_SUPPORT +CFLAGS+= -I${.CURDIR}/../../zfs +CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs +.endif .if ${LOADER_GZIP_SUPPORT} == "yes" CFLAGS+= -DLOADER_GZIP_SUPPORT .endif @@ -47,7 +57,8 @@ CFLAGS+= -DLOADER_TFTP_SUPPORT .if ${MK_FORTH} != "no" # Enable BootForth BOOT_FORTH= yes -CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/sparc64 +CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl +CFLAGS+= -I${.CURDIR}/../../ficl/sparc64 LIBFICL= ${.OBJDIR}/../../ficl/libficl.a .endif @@ -75,8 +86,9 @@ CFLAGS+= -I${.CURDIR}/../../../../lib/li DPADD= ${LIBFICL} ${LIBOFW} ${LIBSTAND} LDADD= ${LIBFICL} ${LIBOFW} -lstand -vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version - sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} +vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version + sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version \ + ${NEWVERSWHAT} loader.help: help.common help.sparc64 cat ${.ALLSRC} | \ Modified: stable/9/sys/boot/sparc64/loader/main.c ============================================================================== --- stable/9/sys/boot/sparc64/loader/main.c Sat May 26 08:44:50 2012 (r236075) +++ stable/9/sys/boot/sparc64/loader/main.c Sat May 26 08:54:26 2012 (r236076) @@ -51,6 +51,9 @@ __FBSDID("$FreeBSD$"); #include <sys/linker.h> #include <sys/queue.h> #include <sys/types.h> +#ifdef LOADER_ZFS_SUPPORT +#include <sys/vtoc.h> +#endif #include <vm/vm.h> #include <machine/asi.h> @@ -143,6 +146,11 @@ static vm_offset_t heapva; static phandle_t root; +#ifdef LOADER_ZFS_SUPPORT +static int zfs_dev_init(void); +#include "zfs.c" +#endif + /* * Machine dependent structures that the machine independent * loader part uses. @@ -154,6 +162,9 @@ struct devsw *devsw[] = { #ifdef LOADER_NET_SUPPORT &netdev, #endif +#ifdef LOADER_ZFS_SUPPORT + &zfs_dev, +#endif 0 }; struct arch_switch archsw; @@ -166,6 +177,7 @@ struct file_format *file_formats[] = { &sparc64_elf, 0 }; + struct fs_ops *file_system[] = { #ifdef LOADER_UFS_SUPPORT &ufs_fsops, @@ -173,6 +185,9 @@ struct fs_ops *file_system[] = { #ifdef LOADER_CD9660_SUPPORT &cd9660_fsops, #endif +#ifdef LOADER_ZFS_SUPPORT + &zfs_fsops, +#endif #ifdef LOADER_ZIP_SUPPORT &zipfs_fsops, #endif @@ -721,6 +736,82 @@ tlb_init_sun4u(void) panic("%s: can't allocate TLB store", __func__); } +#ifdef LOADER_ZFS_SUPPORT + +static int +zfs_dev_init(void) +{ + struct vtoc8 vtoc; + char devname[512]; + spa_t *spa; + vdev_t *vdev; + uint64_t guid; + int fd, part, unit; + + zfs_init(); + + guid = 0; + /* Get the GUID of the ZFS pool on the boot device. */ + fd = open(getenv("currdev"), O_RDONLY); + if (fd != -1) { + if (vdev_probe(vdev_read, (void *)(uintptr_t) fd, &spa) == 0) + guid = spa->spa_guid; + close(fd); + } + + /* Clean up the environment to let ZFS work. */ + while ((vdev = STAILQ_FIRST(&zfs_vdevs)) != NULL) { + STAILQ_REMOVE_HEAD(&zfs_vdevs, v_alllink); + free(vdev); + } + while ((spa = STAILQ_FIRST(&zfs_pools)) != NULL) { + STAILQ_REMOVE_HEAD(&zfs_pools, spa_link); + free(spa); + } + + for (unit = 0; unit < MAXBDDEV; unit++) { + /* Find freebsd-zfs slices in the VTOC. */ + sprintf(devname, "disk%d:", unit); + fd = open(devname, O_RDONLY); + if (fd == -1) + continue; + lseek(fd, 0, SEEK_SET); + if (read(fd, &vtoc, sizeof(vtoc)) != sizeof(vtoc)) { + close(fd); + continue; + } + close(fd); + + for (part = 0; part < 8; part++) { + if (part == 2 || vtoc.part[part].tag != + VTOC_TAG_FREEBSD_ZFS) + continue; + sprintf(devname, "disk%d:%c", unit, part + 'a'); + fd = open(devname, O_RDONLY); + if (fd == -1) + break; + + if (vdev_probe(vdev_read, (void*)(uintptr_t) fd, 0)) + close(fd); + } + } + + if (guid != 0) { + unit = zfs_guid_to_unit(guid); + if (unit >= 0) { + /* Update the environment for ZFS. */ + sprintf(devname, "zfs%d", unit); + env_setenv("currdev", EV_VOLATILE, devname, + ofw_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, devname, + env_noset, env_nounset); + } + } + return (0); +} + +#endif /* LOADER_ZFS_SUPPORT */ + int main(int (*openfirm)(void *)) { @@ -756,14 +847,6 @@ main(int (*openfirm)(void *)) mmu_ops->tlb_init(); /* - * Initialize devices. - */ - for (dp = devsw; *dp != 0; dp++) { - if ((*dp)->dv_init != 0) - (*dp)->dv_init(); - } - - /* * Set up the current device. */ OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)); @@ -780,7 +863,8 @@ main(int (*openfirm)(void *)) * needs to be altered. */ if (bootpath[strlen(bootpath) - 2] == ':' && - bootpath[strlen(bootpath) - 1] == 'f') { + bootpath[strlen(bootpath) - 1] == 'f' && + strstr(bootpath, "cdrom")) { bootpath[strlen(bootpath) - 1] = 'a'; printf("Boot path set to %s\n", bootpath); } @@ -790,6 +874,13 @@ main(int (*openfirm)(void *)) env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset, env_nounset); + /* + * Initialize devices. + */ + for (dp = devsw; *dp != 0; dp++) + if ((*dp)->dv_init != 0) + (*dp)->dv_init(); + printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); Modified: stable/9/sys/boot/sparc64/zfsboot/Makefile ============================================================================== --- head/sys/boot/sparc64/zfsboot/Makefile Tue May 1 17:16:01 2012 (r234898) +++ stable/9/sys/boot/sparc64/zfsboot/Makefile Sat May 26 08:54:26 2012 (r236076) @@ -5,9 +5,5 @@ PROGNAME= zfsboot CFLAGS+= -DZFSBOOT FILES= zfsboot -CLEANFILES+= zfsboot - -zfsboot: boot1 - ln -s ${.ALLSRC} ${.TARGET} .include "${.CURDIR}/../boot1/Makefile" Modified: stable/9/sys/boot/zfs/zfs.c ============================================================================== --- stable/9/sys/boot/zfs/zfs.c Sat May 26 08:44:50 2012 (r236075) +++ stable/9/sys/boot/zfs/zfs.c Sat May 26 08:54:26 2012 (r236076) @@ -399,6 +399,7 @@ zfs_guid_to_unit(uint64_t guid) return (-1); } +#if defined(__amd64__) || defined(__i386__) static int zfs_dev_init(void) { @@ -441,6 +442,7 @@ zfs_dev_init(void) return (0); } +#endif /* * Print information about ZFS pools _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Sat May 26 08:54:44 2012 New Revision: 236077 URL: http://svn.freebsd.org/changeset/base/236077 Log: MFC: r234898, r235207 Add initial support for booting from ZFS on sparc64. At least on Sun Fire V100, the firmware is known to be broken and not allowing to simultaneously open disk devices, causing attempts to boot from a mirror or RAIDZ to cause a crash. This will be worked around later. The firmwares of newer sun4u models don't seem to exhibit this problem though. PR: 165025 Submitted by: Gavin Mu Added: stable/8/sys/boot/sparc64/zfsboot/ - copied from r234898, head/sys/boot/sparc64/zfsboot/ stable/8/sys/boot/sparc64/zfsloader/ - copied from r234898, head/sys/boot/sparc64/zfsloader/ Modified: stable/8/sys/boot/ofw/libofw/devicename.c stable/8/sys/boot/sparc64/Makefile stable/8/sys/boot/sparc64/boot1/Makefile stable/8/sys/boot/sparc64/boot1/boot1.c stable/8/sys/boot/sparc64/loader/Makefile stable/8/sys/boot/sparc64/loader/main.c stable/8/sys/boot/sparc64/zfsboot/Makefile stable/8/sys/boot/zfs/zfs.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/boot/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/e1000/ (props changed) Modified: stable/8/sys/boot/ofw/libofw/devicename.c ============================================================================== --- stable/8/sys/boot/ofw/libofw/devicename.c Sat May 26 08:54:26 2012 (r236076) +++ stable/8/sys/boot/ofw/libofw/devicename.c Sat May 26 08:54:44 2012 (r236077) @@ -28,6 +28,8 @@ __FBSDID("$FreeBSD$"); #include <stand.h> + +#include "bootstrap.h" #include "libofw.h" static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); @@ -76,6 +78,7 @@ ofw_parsedev(struct ofw_devdesc **dev, c phandle_t handle; const char *p; const char *s; + char *ep; char name[256]; char type[64]; int len; @@ -87,9 +90,10 @@ ofw_parsedev(struct ofw_devdesc **dev, c len = s - devspec; bcopy(devspec, name, len); name[len] = '\0'; - if ((handle = OF_finddevice(name)) == -1) - break; - if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) + if ((handle = OF_finddevice(name)) == -1) { + bcopy(name, type, len); + type[len] = '\0'; + } else if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) continue; for (i = 0; (dv = devsw[i]) != NULL; i++) { if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0) @@ -109,6 +113,18 @@ found: strcpy(idev->d_path, name); idev->d_dev = dv; idev->d_type = dv->dv_type; + if (idev->d_type == DEVT_ZFS) { + idev->d_unit = 0; + p = name + strlen(dv->dv_name); + if (*p && (*p != ':')) { + idev->d_unit = strtol(p, &ep, 0); + if (ep == p) { + free(idev); + return (EUNIT); + } + } + } + if (dev == NULL) { free(idev); } else { Modified: stable/8/sys/boot/sparc64/Makefile ============================================================================== --- stable/8/sys/boot/sparc64/Makefile Sat May 26 08:54:26 2012 (r236076) +++ stable/8/sys/boot/sparc64/Makefile Sat May 26 08:54:44 2012 (r236077) @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= boot1 loader +SUBDIR= boot1 loader zfsboot zfsloader .include <bsd.subdir.mk> Modified: stable/8/sys/boot/sparc64/boot1/Makefile ============================================================================== --- stable/8/sys/boot/sparc64/boot1/Makefile Sat May 26 08:54:26 2012 (r236076) +++ stable/8/sys/boot/sparc64/boot1/Makefile Sat May 26 08:54:44 2012 (r236077) @@ -3,22 +3,23 @@ PROG= boot1.elf INTERNALPROG= NO_MAN= -FILES= boot1 +FILES?= boot1 SRCS= _start.s boot1.c +CLEANFILES=${FILES} boot1.aout BOOTBLOCKBASE= 0x4000 -CFLAGS= -mcmodel=medlow -Os -I${.CURDIR}/../../common +CFLAGS+=-mcmodel=medlow -Os -I${.CURDIR}/../../common LDFLAGS=-N -Ttext ${BOOTBLOCKBASE} # Construct boot1. sunlabel expects it to contain zeroed-out space for the # label, and to be of the correct size. -boot1: boot1.aout +${FILES}: boot1.aout + @set -- `ls -l boot1.aout`; x=$$((7680-$$5)); \ + echo "$$x bytes available"; test $$x -ge 0 dd if=/dev/zero of=${.TARGET} bs=512 count=16 dd if=boot1.aout of=${.TARGET} bs=512 oseek=1 conv=notrunc -CLEANFILES= boot1.aout - boot1.aout: boot1.elf elf2aout -o ${.TARGET} ${.ALLSRC} Modified: stable/8/sys/boot/sparc64/boot1/boot1.c ============================================================================== --- stable/8/sys/boot/sparc64/boot1/boot1.c Sat May 26 08:54:26 2012 (r236076) +++ stable/8/sys/boot/sparc64/boot1/boot1.c Sat May 26 08:54:44 2012 (r236077) @@ -20,11 +20,13 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/dirent.h> + #include <machine/elf.h> #include <machine/stdarg.h> -#define _PATH_LOADER "/boot/loader" -#define _PATH_KERNEL "/boot/kernel/kernel" +#define _PATH_LOADER "/boot/loader" +#define _PATH_KERNEL "/boot/kernel/kernel" +#define READ_BUF_SIZE 8192 typedef int putc_func_t(char c, void *arg); typedef int32_t ofwh_t; @@ -45,17 +47,21 @@ static ofwh_t bootdev; static uint32_t fs_off; int main(int ac, char **av); - static void exit(int) __dead2; -static void load(const char *); -static int dskread(void *, u_int64_t, int); - static void usage(void); +#ifdef ZFSBOOT +static void loadzfs(void); +static int zbread(char *buf, off_t off, size_t bytes); +#else +static void load(const char *); +#endif + static void bcopy(const void *src, void *dst, size_t len); static void bzero(void *b, size_t len); static int mount(const char *device); +static int dskread(void *buf, u_int64_t lba, int nblk); static void panic(const char *fmt, ...) __dead2; static int printf(const char *fmt, ...); @@ -312,8 +318,6 @@ strcmp(const char *s1, const char *s2) return ((u_char)*s1 - (u_char)*s2); } -#include "ufsread.c" - int main(int ac, char **av) { @@ -335,14 +339,22 @@ main(int ac, char **av) } } - printf(" \n>> FreeBSD/sparc64 boot block\n" - " Boot path: %s\n" - " Boot loader: %s\n", bootpath, path); +#ifdef ZFSBOOT + printf(" \n>> FreeBSD/sparc64 ZFS boot block\n Boot path: %s\n", + bootpath); +#else + printf(" \n>> FreeBSD/sparc64 boot block\n Boot path: %s\n" + " Boot loader: %s\n", "", bootpath, path); +#endif if (mount(bootpath) == -1) panic("mount"); +#ifdef ZFSBOOT + loadzfs(); +#else load(path); +#endif return (1); } @@ -361,24 +373,86 @@ exit(int code) ofw_exit(); } -static struct dmadat __dmadat; +#ifdef ZFSBOOT + +#define VDEV_BOOT_OFFSET (2 * 256 * 1024) +static char zbuf[READ_BUF_SIZE]; static int -mount(const char *device) +zbread(char *buf, off_t off, size_t bytes) { + size_t len; + off_t poff; + off_t soff; + char *p; + unsigned int nb; + unsigned int lb; - dmadat = &__dmadat; - if ((bootdev = ofw_open(device)) == -1) { - printf("mount: can't open device\n"); - return (-1); + p = buf; + soff = VDEV_BOOT_OFFSET + off; + lb = (soff + bytes + DEV_BSIZE - 1) / DEV_BSIZE; + poff = soff; + while (poff < soff + bytes) { + nb = lb - poff / DEV_BSIZE; + if (nb > READ_BUF_SIZE / DEV_BSIZE) + nb = READ_BUF_SIZE / DEV_BSIZE; + if (dskread(zbuf, poff / DEV_BSIZE, nb)) + break; + if ((poff / DEV_BSIZE + nb) * DEV_BSIZE > soff + bytes) + len = soff + bytes - poff; + else + len = (poff / DEV_BSIZE + nb) * DEV_BSIZE - poff; + memcpy(p, zbuf + poff % DEV_BSIZE, len); + p += len; + poff += len; } - if (fsread(0, NULL, 0)) { - printf("mount: can't read superblock\n"); - return (-1); + return (poff - soff); +} + +static void +loadzfs(void) +{ + Elf64_Ehdr eh; + Elf64_Phdr ph; + caddr_t p; + ino_t ino; + int i; + + if (zbread((char *)&eh, 0, sizeof(eh)) != sizeof(eh)) { + printf("Can't read elf header\n"); + return; } - return (0); + if (!IS_ELF(eh)) { + printf("Not an ELF file\n"); + return; + } + for (i = 0; i < eh.e_phnum; i++) { + fs_off = eh.e_phoff + i * eh.e_phentsize; + if (zbread((char *)&ph, fs_off, sizeof(ph)) != sizeof(ph)) { + printf("Can't read program header %d\n", i); + return; + } + if (ph.p_type != PT_LOAD) + continue; + fs_off = ph.p_offset; + p = (caddr_t)ph.p_vaddr; + if (zbread(p, fs_off, ph.p_filesz) != ph.p_filesz) { + printf("Can't read content of section %d\n", i); + return; + } + if (ph.p_filesz != ph.p_memsz) + bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); + } + ofw_close(bootdev); + (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } +#else + +#include "ufsread.c" + +static struct dmadat __dmadat; + static void load(const char *fname) { @@ -421,6 +495,26 @@ load(const char *fname) (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } +#endif /* ZFSBOOT */ + +static int +mount(const char *device) +{ + + if ((bootdev = ofw_open(device)) == -1) { + printf("mount: can't open device\n"); + return (-1); + } +#ifndef ZFSBOOT + dmadat = &__dmadat; + if (fsread(0, NULL, 0)) { + printf("mount: can't read superblock\n"); + return (-1); + } +#endif + return (0); +} + static int dskread(void *buf, u_int64_t lba, int nblk) { Modified: stable/8/sys/boot/sparc64/loader/Makefile ============================================================================== --- stable/8/sys/boot/sparc64/loader/Makefile Sat May 26 08:54:26 2012 (r236076) +++ stable/8/sys/boot/sparc64/loader/Makefile Sat May 26 08:54:44 2012 (r236077) @@ -3,8 +3,8 @@ .include <bsd.own.mk> MK_SSP= no -PROG= loader -NEWVERSWHAT= "bootstrap loader" sparc64 +PROG?= loader +NEWVERSWHAT?= "bootstrap loader" sparc64 INSTALLFLAGS= -b # Architecture-specific loader code @@ -13,12 +13,17 @@ SRCS= locore.S main.c metadata.c vers.c LOADER_DISK_SUPPORT?= yes LOADER_UFS_SUPPORT?= yes LOADER_CD9660_SUPPORT?= yes +LOADER_ZFS_SUPPORT?= no LOADER_NET_SUPPORT?= yes LOADER_NFS_SUPPORT?= yes LOADER_TFTP_SUPPORT?= yes LOADER_GZIP_SUPPORT?= yes LOADER_BZIP2_SUPPORT?= no +LOADER_DEBUG?= no +.if ${LOADER_DEBUG} == "yes" +CFLAGS+= -DLOADER_DEBUG +.endif .if ${LOADER_DISK_SUPPORT} == "yes" CFLAGS+= -DLOADER_DISK_SUPPORT .endif @@ -28,6 +33,11 @@ CFLAGS+= -DLOADER_UFS_SUPPORT .if ${LOADER_CD9660_SUPPORT} == "yes" CFLAGS+= -DLOADER_CD9660_SUPPORT .endif +.if ${LOADER_ZFS_SUPPORT} == "yes" +CFLAGS+= -DLOADER_ZFS_SUPPORT +CFLAGS+= -I${.CURDIR}/../../zfs +CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs +.endif .if ${LOADER_GZIP_SUPPORT} == "yes" CFLAGS+= -DLOADER_GZIP_SUPPORT .endif @@ -47,7 +57,8 @@ CFLAGS+= -DLOADER_TFTP_SUPPORT .if ${MK_FORTH} != "no" # Enable BootForth BOOT_FORTH= yes -CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/sparc64 +CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl +CFLAGS+= -I${.CURDIR}/../../ficl/sparc64 LIBFICL= ${.OBJDIR}/../../ficl/libficl.a .endif @@ -75,8 +86,9 @@ CFLAGS+= -I${.CURDIR}/../../../../lib/li DPADD= ${LIBFICL} ${LIBOFW} ${LIBSTAND} LDADD= ${LIBFICL} ${LIBOFW} -lstand -vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version - sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} +vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version + sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version \ + ${NEWVERSWHAT} loader.help: help.common help.sparc64 cat ${.ALLSRC} | \ Modified: stable/8/sys/boot/sparc64/loader/main.c ============================================================================== --- stable/8/sys/boot/sparc64/loader/main.c Sat May 26 08:54:26 2012 (r236076) +++ stable/8/sys/boot/sparc64/loader/main.c Sat May 26 08:54:44 2012 (r236077) @@ -51,6 +51,9 @@ __FBSDID("$FreeBSD$"); #include <sys/linker.h> #include <sys/queue.h> #include <sys/types.h> +#ifdef LOADER_ZFS_SUPPORT +#include <sys/vtoc.h> +#endif #include <vm/vm.h> #include <machine/asi.h> @@ -157,6 +160,11 @@ static vm_offset_t heapva; static phandle_t root; +#ifdef LOADER_ZFS_SUPPORT +static int zfs_dev_init(void); +#include "zfs.c" +#endif + /* * Machine dependent structures that the machine independent * loader part uses. @@ -168,6 +176,9 @@ struct devsw *devsw[] = { #ifdef LOADER_NET_SUPPORT &netdev, #endif +#ifdef LOADER_ZFS_SUPPORT + &zfs_dev, +#endif 0 }; struct arch_switch archsw; @@ -180,6 +191,7 @@ struct file_format *file_formats[] = { &sparc64_elf, 0 }; + struct fs_ops *file_system[] = { #ifdef LOADER_UFS_SUPPORT &ufs_fsops, @@ -187,6 +199,9 @@ struct fs_ops *file_system[] = { #ifdef LOADER_CD9660_SUPPORT &cd9660_fsops, #endif +#ifdef LOADER_ZFS_SUPPORT + &zfs_fsops, +#endif #ifdef LOADER_ZIP_SUPPORT &zipfs_fsops, #endif @@ -828,6 +843,82 @@ tlb_init_sun4v(void) memset(tlb_store, 0xFF, SUN4V_TLB_SLOT_MAX * sizeof(*tlb_store)); } +#ifdef LOADER_ZFS_SUPPORT + +static int +zfs_dev_init(void) +{ + struct vtoc8 vtoc; + char devname[512]; + spa_t *spa; + vdev_t *vdev; + uint64_t guid; + int fd, part, unit; + + zfs_init(); + + guid = 0; + /* Get the GUID of the ZFS pool on the boot device. */ + fd = open(getenv("currdev"), O_RDONLY); + if (fd != -1) { + if (vdev_probe(vdev_read, (void *)(uintptr_t) fd, &spa) == 0) + guid = spa->spa_guid; + close(fd); + } + + /* Clean up the environment to let ZFS work. */ + while ((vdev = STAILQ_FIRST(&zfs_vdevs)) != NULL) { + STAILQ_REMOVE_HEAD(&zfs_vdevs, v_alllink); + free(vdev); + } + while ((spa = STAILQ_FIRST(&zfs_pools)) != NULL) { + STAILQ_REMOVE_HEAD(&zfs_pools, spa_link); + free(spa); + } + + for (unit = 0; unit < MAXBDDEV; unit++) { + /* Find freebsd-zfs slices in the VTOC. */ + sprintf(devname, "disk%d:", unit); + fd = open(devname, O_RDONLY); + if (fd == -1) + continue; + lseek(fd, 0, SEEK_SET); + if (read(fd, &vtoc, sizeof(vtoc)) != sizeof(vtoc)) { + close(fd); + continue; + } + close(fd); + + for (part = 0; part < 8; part++) { + if (part == 2 || vtoc.part[part].tag != + VTOC_TAG_FREEBSD_ZFS) + continue; + sprintf(devname, "disk%d:%c", unit, part + 'a'); + fd = open(devname, O_RDONLY); + if (fd == -1) + break; + + if (vdev_probe(vdev_read, (void*)(uintptr_t) fd, 0)) + close(fd); + } + } + + if (guid != 0) { + unit = zfs_guid_to_unit(guid); + if (unit >= 0) { + /* Update the environment for ZFS. */ + sprintf(devname, "zfs%d", unit); + env_setenv("currdev", EV_VOLATILE, devname, + ofw_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, devname, + env_noset, env_nounset); + } + } + return (0); +} + +#endif /* LOADER_ZFS_SUPPORT */ + int main(int (*openfirm)(void *)) { @@ -871,14 +962,6 @@ main(int (*openfirm)(void *)) mmu_ops->tlb_init(); /* - * Initialize devices. - */ - for (dp = devsw; *dp != 0; dp++) { - if ((*dp)->dv_init != 0) - (*dp)->dv_init(); - } - - /* * Set up the current device. */ OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)); @@ -895,7 +978,8 @@ main(int (*openfirm)(void *)) * needs to be altered. */ if (bootpath[strlen(bootpath) - 2] == ':' && - bootpath[strlen(bootpath) - 1] == 'f') { + bootpath[strlen(bootpath) - 1] == 'f' && + strstr(bootpath, "cdrom")) { bootpath[strlen(bootpath) - 1] = 'a'; printf("Boot path set to %s\n", bootpath); } @@ -905,6 +989,13 @@ main(int (*openfirm)(void *)) env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset, env_nounset); + /* + * Initialize devices. + */ + for (dp = devsw; *dp != 0; dp++) + if ((*dp)->dv_init != 0) + (*dp)->dv_init(); + printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); Modified: stable/8/sys/boot/sparc64/zfsboot/Makefile ============================================================================== --- head/sys/boot/sparc64/zfsboot/Makefile Tue May 1 17:16:01 2012 (r234898) +++ stable/8/sys/boot/sparc64/zfsboot/Makefile Sat May 26 08:54:44 2012 (r236077) @@ -5,9 +5,5 @@ PROGNAME= zfsboot CFLAGS+= -DZFSBOOT FILES= zfsboot -CLEANFILES+= zfsboot - -zfsboot: boot1 - ln -s ${.ALLSRC} ${.TARGET} .include "${.CURDIR}/../boot1/Makefile" Modified: stable/8/sys/boot/zfs/zfs.c ============================================================================== --- stable/8/sys/boot/zfs/zfs.c Sat May 26 08:54:26 2012 (r236076) +++ stable/8/sys/boot/zfs/zfs.c Sat May 26 08:54:44 2012 (r236077) @@ -399,6 +399,7 @@ zfs_guid_to_unit(uint64_t guid) return (-1); } +#if defined(__amd64__) || defined(__i386__) static int zfs_dev_init(void) { @@ -441,6 +442,7 @@ zfs_dev_init(void) return (0); } +#endif /* * Print information about ZFS pools _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Mon Jun 4 20:45:33 2012 New Revision: 236579 URL: http://svn.freebsd.org/changeset/base/236579 Log: The workaround added in r151650 for handling firmwares that don't allow a single device to be opened multiple times concurrently unfortunately isn't sufficient with ZFS. This is due to the fact, that ZFS may open different partitions of a single device simultaneously. So the best we can do in this case is to cache the lastly used device path and close and open devices in ofwd_strategy() as needed. PR: 165025 Submitted by: Gavin Mu MFC after: 1 week Modified: head/sys/boot/ofw/libofw/ofw_disk.c Modified: head/sys/boot/ofw/libofw/ofw_disk.c ============================================================================== --- head/sys/boot/ofw/libofw/ofw_disk.c Mon Jun 4 20:36:11 2012 (r236578) +++ head/sys/boot/ofw/libofw/ofw_disk.c Mon Jun 4 20:45:33 2012 (r236579) @@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$"); */ #include <sys/param.h> -#include <sys/queue.h> #include <netinet/in.h> @@ -43,8 +42,8 @@ __FBSDID("$FreeBSD$"); #include "libofw.h" static int ofwd_init(void); -static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, - size_t size, char *buf, size_t *rsize); +static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, + size_t size, char *buf, size_t *rsize); static int ofwd_open(struct open_file *f, ...); static int ofwd_close(struct open_file *f); static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data); @@ -61,120 +60,109 @@ struct devsw ofwdisk = { ofwd_print }; -struct opened_dev { - ihandle_t handle; - u_int count; - SLIST_ENTRY(opened_dev) link; -}; - -SLIST_HEAD(, opened_dev) opened_devs = SLIST_HEAD_INITIALIZER(opened_devs); +/* + * We're not guaranteed to be able to open a device more than once and there + * is no OFW standard method to determine whether a device is already opened. + * Opening a device multiple times simultaneously happens to work with most + * OFW block device drivers but triggers a trap with at least the driver for + * the on-board controllers of Sun Fire V100 and Ultra 1. Upper layers and MI + * code expect to be able to open a device more than once however. Given that + * different partitions of the same device might be opened at the same time as + * done by ZFS, we can't generally just keep track of the opened devices and + * reuse the instance handle when asked to open an already opened device. So + * the best we can do is to cache the lastly used device path and close and + * open devices in ofwd_strategy() as needed. + */ +static struct ofw_devdesc *kdp; static int ofwd_init(void) { - return 0; + return (0); } static int -ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, - size_t *rsize) +ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t size, + char *buf, size_t *rsize) { struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata; daddr_t pos; int n; + if (dp != kdp) { + if (kdp != NULL) { +#if !defined(__powerpc__) + OF_close(kdp->d_handle); +#endif + kdp = NULL; + } + if ((dp->d_handle = OF_open(dp->d_path)) == -1) + return (ENOENT); + kdp = dp; + } + pos = dblk * 512; do { if (OF_seek(dp->d_handle, pos) < 0) - return EIO; + return (EIO); n = OF_read(dp->d_handle, buf, size); if (n < 0 && n != -2) - return EIO; + return (EIO); } while (n == -2); *rsize = size; - return 0; + return (0); } static int ofwd_open(struct open_file *f, ...) { - char path[256]; struct ofw_devdesc *dp; - struct opened_dev *odp; va_list vl; va_start(vl, f); dp = va_arg(vl, struct ofw_devdesc *); va_end(vl); - /* - * We're not guaranteed to be able to open a device more than once - * simultaneously and there is no OFW standard method to determine - * whether a device is already opened. Opening a device more than - * once happens to work with most OFW block device drivers but - * triggers a trap with at least the driver for the on-board SCSI - * controller in Sun Ultra 1. Upper layers and MI code expect to - * be able to open a device more than once however. As a workaround - * keep track of the opened devices and reuse the instance handle - * when asked to open an already opened device. - */ - SLIST_FOREACH(odp, &opened_devs, link) { - if (OF_instance_to_path(odp->handle, path, sizeof(path)) == -1) - continue; - if (strcmp(path, dp->d_path) == 0) { - odp->count++; - dp->d_handle = odp->handle; - return 0; + + if (dp != kdp) { + if (kdp != NULL) { + OF_close(kdp->d_handle); + kdp = NULL; } + if ((dp->d_handle = OF_open(dp->d_path)) == -1) { + printf("%s: Could not open %s\n", __func__, + dp->d_path); + return (ENOENT); + } + kdp = dp; } - odp = malloc(sizeof(struct opened_dev)); - if (odp == NULL) { - printf("ofwd_open: malloc failed\n"); - return ENOMEM; - } - if ((odp->handle = OF_open(dp->d_path)) == -1) { - printf("ofwd_open: Could not open %s\n", dp->d_path); - free(odp); - return ENOENT; - } - odp->count = 1; - SLIST_INSERT_HEAD(&opened_devs, odp, link); - dp->d_handle = odp->handle; - return 0; + return (0); } static int ofwd_close(struct open_file *f) { struct ofw_devdesc *dev = f->f_devdata; - struct opened_dev *odp; - SLIST_FOREACH(odp, &opened_devs, link) { - if (odp->handle == dev->d_handle) { - odp->count--; - if (odp->count == 0) { - SLIST_REMOVE(&opened_devs, odp, opened_dev, - link); - #if !defined(__powerpc__) - OF_close(odp->handle); - #endif - free(odp); - } - break; - } + if (dev == kdp) { +#if !defined(__powerpc__) + OF_close(dev->d_handle); +#endif + kdp = NULL; } - return 0; + return (0); } static int -ofwd_ioctl(struct open_file *f, u_long cmd, void *data) +ofwd_ioctl(struct open_file *f __unused, u_long cmd __unused, + void *data __unused) { return (EINVAL); } static void -ofwd_print(int verbose) +ofwd_print(int verbose __unused) { } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Thu Jun 14 19:55:19 2012 New Revision: 237091 URL: http://svn.freebsd.org/changeset/base/237091 Log: MFC: r236579 The workaround added in r151650 for handling firmwares that don't allow a single device to be opened multiple times concurrently unfortunately isn't sufficient with ZFS. This is due to the fact, that ZFS may open different partitions of a single device simultaneously. So the best we can do in this case is to cache the lastly used device path and close and open devices in ofwd_strategy() as needed. PR: 165025 Submitted by: Gavin Mu Modified: stable/9/sys/boot/ofw/libofw/ofw_disk.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/amd64/include/xen/ (props changed) stable/9/sys/boot/ (props changed) stable/9/sys/boot/i386/efi/ (props changed) stable/9/sys/boot/ia64/efi/ (props changed) stable/9/sys/boot/ia64/ski/ (props changed) stable/9/sys/boot/powerpc/boot1.chrp/ (props changed) stable/9/sys/boot/powerpc/ofw/ (props changed) stable/9/sys/cddl/contrib/opensolaris/ (props changed) stable/9/sys/conf/ (props changed) stable/9/sys/contrib/dev/acpica/ (props changed) stable/9/sys/contrib/octeon-sdk/ (props changed) stable/9/sys/contrib/pf/ (props changed) stable/9/sys/contrib/x86emu/ (props changed) stable/9/sys/dev/ (props changed) stable/9/sys/dev/e1000/ (props changed) stable/9/sys/dev/ixgbe/ (props changed) stable/9/sys/fs/ (props changed) stable/9/sys/fs/ntfs/ (props changed) stable/9/sys/modules/ (props changed) Modified: stable/9/sys/boot/ofw/libofw/ofw_disk.c ============================================================================== --- stable/9/sys/boot/ofw/libofw/ofw_disk.c Thu Jun 14 19:30:31 2012 (r237090) +++ stable/9/sys/boot/ofw/libofw/ofw_disk.c Thu Jun 14 19:55:19 2012 (r237091) @@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$"); */ #include <sys/param.h> -#include <sys/queue.h> #include <netinet/in.h> @@ -43,8 +42,8 @@ __FBSDID("$FreeBSD$"); #include "libofw.h" static int ofwd_init(void); -static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, - size_t size, char *buf, size_t *rsize); +static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, + size_t size, char *buf, size_t *rsize); static int ofwd_open(struct open_file *f, ...); static int ofwd_close(struct open_file *f); static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data); @@ -61,120 +60,109 @@ struct devsw ofwdisk = { ofwd_print }; -struct opened_dev { - ihandle_t handle; - u_int count; - SLIST_ENTRY(opened_dev) link; -}; - -SLIST_HEAD(, opened_dev) opened_devs = SLIST_HEAD_INITIALIZER(opened_devs); +/* + * We're not guaranteed to be able to open a device more than once and there + * is no OFW standard method to determine whether a device is already opened. + * Opening a device multiple times simultaneously happens to work with most + * OFW block device drivers but triggers a trap with at least the driver for + * the on-board controllers of Sun Fire V100 and Ultra 1. Upper layers and MI + * code expect to be able to open a device more than once however. Given that + * different partitions of the same device might be opened at the same time as + * done by ZFS, we can't generally just keep track of the opened devices and + * reuse the instance handle when asked to open an already opened device. So + * the best we can do is to cache the lastly used device path and close and + * open devices in ofwd_strategy() as needed. + */ +static struct ofw_devdesc *kdp; static int ofwd_init(void) { - return 0; + return (0); } static int -ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, - size_t *rsize) +ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t size, + char *buf, size_t *rsize) { struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata; daddr_t pos; int n; + if (dp != kdp) { + if (kdp != NULL) { +#if !defined(__powerpc__) + OF_close(kdp->d_handle); +#endif + kdp = NULL; + } + if ((dp->d_handle = OF_open(dp->d_path)) == -1) + return (ENOENT); + kdp = dp; + } + pos = dblk * 512; do { if (OF_seek(dp->d_handle, pos) < 0) - return EIO; + return (EIO); n = OF_read(dp->d_handle, buf, size); if (n < 0 && n != -2) - return EIO; + return (EIO); } while (n == -2); *rsize = size; - return 0; + return (0); } static int ofwd_open(struct open_file *f, ...) { - char path[256]; struct ofw_devdesc *dp; - struct opened_dev *odp; va_list vl; va_start(vl, f); dp = va_arg(vl, struct ofw_devdesc *); va_end(vl); - /* - * We're not guaranteed to be able to open a device more than once - * simultaneously and there is no OFW standard method to determine - * whether a device is already opened. Opening a device more than - * once happens to work with most OFW block device drivers but - * triggers a trap with at least the driver for the on-board SCSI - * controller in Sun Ultra 1. Upper layers and MI code expect to - * be able to open a device more than once however. As a workaround - * keep track of the opened devices and reuse the instance handle - * when asked to open an already opened device. - */ - SLIST_FOREACH(odp, &opened_devs, link) { - if (OF_instance_to_path(odp->handle, path, sizeof(path)) == -1) - continue; - if (strcmp(path, dp->d_path) == 0) { - odp->count++; - dp->d_handle = odp->handle; - return 0; + + if (dp != kdp) { + if (kdp != NULL) { + OF_close(kdp->d_handle); + kdp = NULL; } + if ((dp->d_handle = OF_open(dp->d_path)) == -1) { + printf("%s: Could not open %s\n", __func__, + dp->d_path); + return (ENOENT); + } + kdp = dp; } - odp = malloc(sizeof(struct opened_dev)); - if (odp == NULL) { - printf("ofwd_open: malloc failed\n"); - return ENOMEM; - } - if ((odp->handle = OF_open(dp->d_path)) == -1) { - printf("ofwd_open: Could not open %s\n", dp->d_path); - free(odp); - return ENOENT; - } - odp->count = 1; - SLIST_INSERT_HEAD(&opened_devs, odp, link); - dp->d_handle = odp->handle; - return 0; + return (0); } static int ofwd_close(struct open_file *f) { struct ofw_devdesc *dev = f->f_devdata; - struct opened_dev *odp; - SLIST_FOREACH(odp, &opened_devs, link) { - if (odp->handle == dev->d_handle) { - odp->count--; - if (odp->count == 0) { - SLIST_REMOVE(&opened_devs, odp, opened_dev, - link); - #if !defined(__powerpc__) - OF_close(odp->handle); - #endif - free(odp); - } - break; - } + if (dev == kdp) { +#if !defined(__powerpc__) + OF_close(dev->d_handle); +#endif + kdp = NULL; } - return 0; + return (0); } static int -ofwd_ioctl(struct open_file *f, u_long cmd, void *data) +ofwd_ioctl(struct open_file *f __unused, u_long cmd __unused, + void *data __unused) { return (EINVAL); } static void -ofwd_print(int verbose) +ofwd_print(int verbose __unused) { } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Thu Jun 14 19:55:22 2012 New Revision: 237092 URL: http://svn.freebsd.org/changeset/base/237092 Log: MFC: r236579 The workaround added in r151650 for handling firmwares that don't allow a single device to be opened multiple times concurrently unfortunately isn't sufficient with ZFS. This is due to the fact, that ZFS may open different partitions of a single device simultaneously. So the best we can do in this case is to cache the lastly used device path and close and open devices in ofwd_strategy() as needed. PR: 165025 Submitted by: Gavin Mu Modified: stable/8/sys/boot/ofw/libofw/ofw_disk.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/boot/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/e1000/ (props changed) Modified: stable/8/sys/boot/ofw/libofw/ofw_disk.c ============================================================================== --- stable/8/sys/boot/ofw/libofw/ofw_disk.c Thu Jun 14 19:55:19 2012 (r237091) +++ stable/8/sys/boot/ofw/libofw/ofw_disk.c Thu Jun 14 19:55:22 2012 (r237092) @@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$"); */ #include <sys/param.h> -#include <sys/queue.h> #include <netinet/in.h> @@ -43,8 +42,8 @@ __FBSDID("$FreeBSD$"); #include "libofw.h" static int ofwd_init(void); -static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, - size_t size, char *buf, size_t *rsize); +static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, + size_t size, char *buf, size_t *rsize); static int ofwd_open(struct open_file *f, ...); static int ofwd_close(struct open_file *f); static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data); @@ -61,120 +60,109 @@ struct devsw ofwdisk = { ofwd_print }; -struct opened_dev { - ihandle_t handle; - u_int count; - SLIST_ENTRY(opened_dev) link; -}; - -SLIST_HEAD(, opened_dev) opened_devs = SLIST_HEAD_INITIALIZER(opened_devs); +/* + * We're not guaranteed to be able to open a device more than once and there + * is no OFW standard method to determine whether a device is already opened. + * Opening a device multiple times simultaneously happens to work with most + * OFW block device drivers but triggers a trap with at least the driver for + * the on-board controllers of Sun Fire V100 and Ultra 1. Upper layers and MI + * code expect to be able to open a device more than once however. Given that + * different partitions of the same device might be opened at the same time as + * done by ZFS, we can't generally just keep track of the opened devices and + * reuse the instance handle when asked to open an already opened device. So + * the best we can do is to cache the lastly used device path and close and + * open devices in ofwd_strategy() as needed. + */ +static struct ofw_devdesc *kdp; static int ofwd_init(void) { - return 0; + return (0); } static int -ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, - size_t *rsize) +ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t size, + char *buf, size_t *rsize) { struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata; daddr_t pos; int n; + if (dp != kdp) { + if (kdp != NULL) { +#if !defined(__powerpc__) + OF_close(kdp->d_handle); +#endif + kdp = NULL; + } + if ((dp->d_handle = OF_open(dp->d_path)) == -1) + return (ENOENT); + kdp = dp; + } + pos = dblk * 512; do { if (OF_seek(dp->d_handle, pos) < 0) - return EIO; + return (EIO); n = OF_read(dp->d_handle, buf, size); if (n < 0 && n != -2) - return EIO; + return (EIO); } while (n == -2); *rsize = size; - return 0; + return (0); } static int ofwd_open(struct open_file *f, ...) { - char path[256]; struct ofw_devdesc *dp; - struct opened_dev *odp; va_list vl; va_start(vl, f); dp = va_arg(vl, struct ofw_devdesc *); va_end(vl); - /* - * We're not guaranteed to be able to open a device more than once - * simultaneously and there is no OFW standard method to determine - * whether a device is already opened. Opening a device more than - * once happens to work with most OFW block device drivers but - * triggers a trap with at least the driver for the on-board SCSI - * controller in Sun Ultra 1. Upper layers and MI code expect to - * be able to open a device more than once however. As a workaround - * keep track of the opened devices and reuse the instance handle - * when asked to open an already opened device. - */ - SLIST_FOREACH(odp, &opened_devs, link) { - if (OF_instance_to_path(odp->handle, path, sizeof(path)) == -1) - continue; - if (strcmp(path, dp->d_path) == 0) { - odp->count++; - dp->d_handle = odp->handle; - return 0; + + if (dp != kdp) { + if (kdp != NULL) { + OF_close(kdp->d_handle); + kdp = NULL; } + if ((dp->d_handle = OF_open(dp->d_path)) == -1) { + printf("%s: Could not open %s\n", __func__, + dp->d_path); + return (ENOENT); + } + kdp = dp; } - odp = malloc(sizeof(struct opened_dev)); - if (odp == NULL) { - printf("ofwd_open: malloc failed\n"); - return ENOMEM; - } - if ((odp->handle = OF_open(dp->d_path)) == -1) { - printf("ofwd_open: Could not open %s\n", dp->d_path); - free(odp); - return ENOENT; - } - odp->count = 1; - SLIST_INSERT_HEAD(&opened_devs, odp, link); - dp->d_handle = odp->handle; - return 0; + return (0); } static int ofwd_close(struct open_file *f) { struct ofw_devdesc *dev = f->f_devdata; - struct opened_dev *odp; - SLIST_FOREACH(odp, &opened_devs, link) { - if (odp->handle == dev->d_handle) { - odp->count--; - if (odp->count == 0) { - SLIST_REMOVE(&opened_devs, odp, opened_dev, - link); - #if !defined(__powerpc__) - OF_close(odp->handle); - #endif - free(odp); - } - break; - } + if (dev == kdp) { +#if !defined(__powerpc__) + OF_close(dev->d_handle); +#endif + kdp = NULL; } - return 0; + return (0); } static int -ofwd_ioctl(struct open_file *f, u_long cmd, void *data) +ofwd_ioctl(struct open_file *f __unused, u_long cmd __unused, + void *data __unused) { return (EINVAL); } static void -ofwd_print(int verbose) +ofwd_print(int verbose __unused) { } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
State Changed From-To: open->closed Close, thanks for submitting!