Creating ext3/swap partitions on Tomato

Discussion in 'Tomato Firmware' started by Monk E. Boy, Oct 18, 2012.

  1. Monk E. Boy

    Monk E. Boy Network Guru Member

    Koitsu suggested I write some instructions on how to setup USB devices with ext2/ext3/swap/etc. partitions natively in Tomato, since it might be useful for others, and since I do this on a (somehwat) regular basis I thought I take notes this time around.

    Apologies if these notes are a little rough around the edges for novice users, or too wordy for the technically inclined. My notes were written in a fixed width font, but I'm not sure how to format it that way so tabs, etc. will line up properly; I can see they're a bit of a nightmare in their current form, but at least I numbered the steps.

    For phase 1 I'll use the GUI to make things more simple (believe it or not):

    1) Plug in USB storage device to router
    1a) For simplicity's sake, make sure you have only one USB device attached, to avoid making a mistake and wiping out a different device.
    2) Open your favorite web browser, log into the Tomato website
    3) Select USB and NAS, then USB Support
    4) Device should be listed under "Attached Devices" at bottom of page.
    4a) USB devices tend to be slow to mount, so patience helps. I usually get up and grab a cup of coffee rather than refresh-refresh-refresh.
    4b) If router doesn't recognize the USB device, verify core USB support & USB storage support are enabled. Remember to hit Save after changing settings. Give it some time, at least a couple minutes, then refresh the page and see if it's listed.
    4c) Some devices only work if USB printer support is disabled, others require USB 3G modem support to be disabled. Remember to hit Save. Give it some time then refresh.
    4d) Occasionally I've noticed toggling on USB 1.1 Support kickstarts the process. Remember to hit Save. Give it some time then refresh.
    4e) If all else fails, and all settings are configured, try to reboot router.
    4f) Typically once the router has mounted the device it'll continue to recognize it, so you can probably turn on USB printer sharing, 3G modem support, disable USB 1.1, etc. and it'll still stay mounted. YMMV (your mileage may vary)
    5) After device is listed as an Attached Device, click on Unmount
    6) Mounted? should then change from Yes to No
    7) Close your web browser.

    CLI for phase 2:

    Commands here follow the step's initial instructions/explanation, which are then followed by some example output. Any subsequent commands follow the output, and so on, within a step.

    8) Login to router over telnet or ssh (putty for Windows is free and supports both)
    9) List existing devices and partitions:
    fdisk -l

    Disk /dev/sda: 3941 MB, 3941597184 bytes
    255 heads, 63 sectors/track, 479 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sda1 * 1 480 3849152 b Win95 FAT32
    Partition 1 has different physical/logical endings:
    phys=(478, 254, 63) logical=(479, 52, 21)

    9a) In my example, the device is /dev/sda and contains partition /dev/sda1 that uses a FAT32 format.
    9b) It will probably be this or /dev/sdb and /dev/sdb1 but you need to read and interpret what it says
    9c) /dev/jffs and /jffs is the JFFS filesystem, you do not want to touch it; do not run fdisk on a jffs device
    9d) If you are at all confused STOP RIGHT NOW and ask for help!

    10) Now we're going to create a new partition map and partitions:
    fdisk /dev/sda

    11) Create a new blank paritition table:

    Building a new DOS disklabel. Changes will remain in memory only,
    until you decide to write them. After that the previous content
    won't be recoverable.

    12) Add a new primary partition, partition number 1:

    e extended
    p primary partition (1-4)

    Partition number (1-4)

    First cylinder (1-479, default 1)
    Hit enter for default

    Last cylinder or +size or +sizeM or +sizeK (1-479, default 479)
    For a single partition you can hit enter to use the entire disk. I want to create a swap partition so I will type +500M for a 500MB swap partition:

    12a) Since I'm creating a swap partition I need to set the partition type:

    Selected partition 1
    Hex code (type L to list codes)

    You can type L to list all types of filesystems, but 82 is Linux swap, so that's what I'll type:

    13) Now I want to create a 2nd primary partition for ext3 data storage:

    e extended
    p primary partition (1-4)

    Partition number (1-4)

    Because partition 1 was just created as swap, we want to create partition 2:

    First cylinder (63-479, default 63)
    Hit enter for default (in this case, 63).

    Last cylinder or +size or +sizeM or +sizeK (63-479, default 479)
    Hit enter to use the entire disk for partition 2, or if you want to use a specific value (e.g. to create a 3rd, 4th, etc. partition) then type +###M with the appropriate numeric value like I did for swap.

    If you want to create 3rd, 4th, etc. partitions then go back and create them. Otherwise continue on to the next step.

    14) Now that my two partitions are created I'm going to verify the partition map is how I want it by printing it to screen.

    Disk /dev/sda: 3941 MB, 3941597184 bytes
    255 heads, 63 sectors/track, 479 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    /dev/sda1 1 62 497983+ 82 Linux swap
    /dev/sda2 63 479 3349552+ 83 Linux

    15) Now ask yourself: Is this how you want the disk to be? Are you sure? Are you really, really sure? If no then hold down control & press c to break out of fdisk and abort all changes. If yes, then you need to write it to disk.

    Calling ioctl() to re-read partition table

    You will then be dropped back to the shell prompt. If you failed to unmount the filesystem an error will be displayed after ioctl. This error means fdisk couldn't write the partition map to disk, and your old partitions are still intact. Go back to step one and unmount the partition(s).

    16) Okay now you have your partitions there, and it's time to format them. Since I created a swap partition, I'll format that one first, giving it the label "swap":
    mkswap -L swap /dev/sda1

    16a) Now to format my 2nd partition as ext3, giving it the label "Data":
    mkfs.ext3 -L Data /dev/sda2

    mke2fs 1.38 (30-Jun-2005)
    Filesystem label=Data
    OS type: Linux
    Block size=4096 (log=2)
    Fragment size=4096 (log=2)
    419328 inodes, 837388 blocks
    41869 blocks (5.00%) reserved for the super user
    First data block=0
    26 block groups
    32768 blocks per group, 32768 fragments per group
    16128 inodes per group
    Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200

    Writing inode tables: done
    Creating journal (16384 blocks): done
    Writing superblocks and filesystem accounting information: done
    This filesystem will be automatically checked every 20 mounts or
    180 days, whichever comes first. Use tune2fs -c or -i to override.

    17) And you're back to a shell prompt. You can either reboot the router by typing:

    At which point the router will reboot, and the default mounts will take effect.

    Or you can manually mount the partitions. Because I gave the partition the label "Data" it will mount to /tmp/mnt/Data. Therefore I would type:
    mkdir /tmp/mnt/Data
    mount /dev/sda2 /tmp/mnt/Data

    Which would mount my Data partition. If you labelled your partition "Stuff" it would mount to /tmp/mnt/Stuff instead. If you leave the label blank it will mount with the device name, which will change depending on which USB port its plugged into (which is why labels are a Very Good Idea). Make sure your labels are unique across devices, you don't need two partitions called Data (just call the other one Lore).

    18) To enable swap:
    swapon /dev/sda1

    Note that swapon only affects the current state of the router. If you reboot swap gets disabled. To "permanently" enable swap call swapon in either the Init or Firewall tab under Administration -> Scripts. As far as I can tell the label is ignored by swapon, so if you shuffle the drive between ports then you'll need to adjust swapon to the new device name.

    18a) Do not enable swap on flash-based devices unless you like destroying flash-based devices. For short term purposes it will be perfectly fine, but if you need swap enabled 24/7 to run something from optware/entware/etc. 24/7 then you need to put your swap on a hard disk. I create them for what-if-I-need-swap-at-the-remote-site-in-6-months emergency purposes, purely a temporary solution to allow the full range of possibilities at a future date. If I needed to enable it permanently I would go through the trouble of partitioning a HD this way and using that instead (or, likely, in addition to flash).

    One last note, if you wanted to format in ext2 instead of ext3, you would use the mkfs.ext2 command instead of mkfs.ext3. Aside from changing 3 to a 2 the command line is otherwise identical (the output will be slightly different).
    K34nut, menses and koitsu like this.
  2. menses

    menses LI Guru Member

    What is the most elegant way of automatically activating the swap? Using one of the scripts as mentioned in your guide or using /etc/fstab?
    For example:
    LABEL=Swap none swap sw 0 0
    LABEL=Data /mnt/data ext3 rw,noatime 1 1
    This of course requires setting /etc/fstab to NVRAM:
    nvram setfile2nvram /etc/fstab
    nvram commit
    Will using /etc/fstab break something in Tomato? Does it work with the automount option in the USB AND NAS --> USB Support page (I mean the option which says: "Automatically mount all partitions to sub-directories in /mnt")?
  3. koitsu

    koitsu Network Guru Member

    I would advocate to enable swap, you simply add a single-line entry to WAN Up that says swapon /wherever/swap/partition/is. The reason I state using WAN Up rather than Init is that there are confirmed reports of the USB layer sometimes taking a little while to enumerate all devices on the bus, so putting the script in Init can cause it to intermittently fail (i.e. /wherever/swap/partition/is is non-existent, but 3 seconds later does exist). I do not advocate using sleep to get around this.

    That said: sure, you can use /etc/fstab if you want, but the same issue as what I just described applies, not to mention you're now wasting more NVRAM. :)
  4. menses

    menses LI Guru Member

    Ah, I see. I was just about to use the NVRAM way because I have also a partition for /opt and it would have been easy to also mount it through /etc/fstab. But after reading your message I think the WAN Up script is the best solution. I guess I should do the /opt mounting there too. Or remounting or rebinding as in:
    mount -o bind /tmp/mnt/OPTWARE /opt
    Any comments on this? I'm assuming that in Tomato the automount is run before WAN Up (or else this would not work).
  5. koitsu

    koitsu Network Guru Member

    The aforementioned "mount bind" is what I use on my own router, except I use it for CIFS (rather than USB). Specifically the option Administration -> CIFS Client -> ... -> Execute When Mounted, which I set to mount -o bind /cifs1/opt /opt (since I use Entware).

    Anything under Scripts -> Init gets run "ASAP", meaning immediately after the router has a usable root filesystem. These commands can take place before things like network mounts are up/functional and the USB layer has fully enumerated all devices.

    Anything under Scripts -> Firewall gets run after the firewall rules (based on GUI options, port forwards, etc.) get put into place. This is done before the WAN comes up (obviously, for security reasons). These commands also can take place before things like network mounts are up/functional and the USB layer has fully enumerated all devices.

    Anything under Scripts -> WAN Up gets run after the WAN interface gets an IP address. These commands usually take place after things like network mounts are up/functional and USB enumeration. I use the word "usually" because the underlying code does not actually determine if that's the case; it's just total chance that doing DHCP + etc. (assuming you do use DHCP) on the WAN adds some time/delay, thus giving the rest of the startup system a chance to finish its simultaneous tasks (re: network mounts, USB enumeration, etc.). So basically most extraneous "stuff" should probably go here.

    Anything under Scripts -> Shutdown should be obvious.

    TL;DR -- It sounds to me like there needs to be an option under the USB section that mimics the Execute When Mounted feature that's available in the CIFS section.
    Monk E. Boy and menses like this.
  6. menses

    menses LI Guru Member

    I tried these two lines:
    /sbin/swapon /dev/sda1
    /bin/mount -o bind /tmp/mnt/OPTWARE /opt
    in Scripts -> WAN Up.
    And it works.

    However I was just thinking why not use the Run after mounting feature in USB AND NAS -> USB Support. Isn't this similar to the Execute When Mounted feature in the CIFS section?

    BTW, Tomato's swapon doesn't seem to support the -L (label) switch. Now I have to refer to the swap partition by the device name which can change depending on how many USB storage devices are attached to the router. This is annoying :)
  7. rhester72

    rhester72 Network Guru Member

    Best way to handle swap and labels is to not to, since swap by definition _should_ not (note I didn't write cannot) allow labels.

    My fstab looks like:

    UUID=ceb8e7db-4b85-46bc-bc65-5cc72e7d7b32 none swap sw 0 0
    which I got by...
    # blkid /dev/sda2
    /dev/sda2: UUID="ceb8e7db-4b85-46bc-bc65-5cc72e7d7b32"
    menses likes this.
  8. menses

    menses LI Guru Member

    Interesting. Why swap shouldn't use labels?

    By the way, I think the mount -o bind command is problematic when run from a script. If the script is run multiple times there will be multiple (duplicate) binds for the same directories. I'm not sure if this could cause errors but it sure doesn't look very clean.
    Here's what it looks like when using the WAN Up script and the network gets a reboot:
    # mount
    /dev/sda2 on /tmp/mnt/OPTWARE type ext3 (rw,nodev,noatime,data=ordered)
    /dev/sda3 on /tmp/mnt/DATA type ext3 (rw,nodev,noatime,data=ordered)
    /dev/sda2 on /opt type ext3 (rw,nodev,noatime,data=ordered)
    /dev/sda2 on /opt type ext3 (rw,nodev,noatime,data=ordered)
  9. rhester72

    rhester72 Network Guru Member

    Swap shouldn't use labels because it has no filesystem. Think about what I said for a moment...if there's no filesystem, where does the label go? (Hint: The broken current Linux implementation can and will eventually result in your label being overwritten.)

    Best way to handle "double mounts" is either...

    a) Use <mountroot>/mount.autorun to do the mount (won't repeat unless you un/replug the USB drive


    b) Use some sort of flag (touch /var/notice/mymount, etc.) to indicate when the mount has happened and check for the flag before mounting.

    Monk E. Boy and menses like this.
  10. Monk E. Boy

    Monk E. Boy Network Guru Member

    Well, that explains why I never figured out a way to use the label in any meaningful way on swap.

    I would bet that every time the WAN port "bounces" that WAN Up gets run. How about calling a script, located in /tmp/mnt/Data (since I assume the contents of WAN Up get written to NVRAM like most things, best to keep stuff short), that checks if /tmp/mnt/Data is already mounted to /opt before attempting to remount it.

    Or make /opt a soft/hard link to /tmp/mnt/Data. Er, unless that breaks something...
  11. koitsu

    koitsu Network Guru Member

    Yup, well-known stupidity of the utility, and you are correct -- it can cause problems. There are many, many ways to solve this. The proper way as I see it is to do this in your Init script section (remember, it's just shell/bash!):

    if ! grep -q -s "/opt" /proc/mounts; then
      mount -o bind /whatever /opt
    It's important you understand what the -q and -s flags to Linux grep do.

    If you want to do this as a one-liner, you may or may not be able to get this to work with the Execute When Mounted (CIFS) or Run after mounting (USB) features. I would need to look at the code to see if they're blind calls to system(), if they do fork() with execl(), or what. It matters tremendously. The one-liner would be this:

    if ! grep -q -s "/opt" /proc/mounts; then mount -o bind /whatever /opt; fi
    There is an alternate option but I cannot recommend it in the least, because it will either a) screw up any program which is using /opt at the time (including daemons, etc.) or b) cause the mount command to block (wait) indefinitely if a file happens to have a lock. You might be able to work around this using the mount -f flag, but how an underlying program handles a file descriptor thats' now pointing to a file on a filesystem that's gone is spotty at best - some code does not have proper error handlers for this situation (you'd be surprised how much software on *IX assumes the filesystem will never go away; this becomes even more tricky/dangerous/complex if the program is a daemon). Anyway, that alternate option is this:

    mount -o bind,remount /whatever /opt
    Again: please do not use the latter unless you are damn sure of what the repercussions are. I won't be held liable if your router shits itself or you log in to it one day and find 7 "mount" processes running because your WAN has gone up/down 7 times.
    Monk E. Boy and menses like this.
  12. menses

    menses LI Guru Member

    Thanks, I had completely forgotten the .autorun/.autostop system. I've used it before in my previous routers/Teddy_Bear's mods but didn't remember it at all until you mentioned it.

    So I made a little .autorun script in /opt:
    # ls -l /opt/mount.autorun
    -rwx------    1 root    root            52 Nov  8 14:11 mount.autorun
    # cat /opt/mount.autorun
    /bin/mount -o bind /tmp/mnt/OPTWARE /opt
    (Actually I'm using Entware, but for some reason I'm still using Optware for the labels. I guess I should change that. :) )

    I'm curious why you are activating your swap in fstab? As @koitsu pointed out sometimes the USB loads so slow that there's no disk available when fstab is read. I've encountered this only a few times but it does happen. (I've got a couple of "Where's my data partition?!" calls from my dad when his router doesn't mount the USB partitions.)

    Thanks for the detailed suggestion. I think the .autorun script works for this case very well. And uses less NVRAM than the Admin Scripts. ;)
    ThanatosUA and koitsu like this.
  13. rhester72

    rhester72 Network Guru Member

    I've never had any trouble doing it via fstab, and I've never found a way to bring swap online via CLI using UUID. I'm aware of the possible race condition but hasn't bitten me (yet). *laughs*

    menses likes this.
  14. menses

    menses LI Guru Member

    Yeah, too bad the swapon that's bundled with Tomato also lacks the -U (UUID) switch.

    Well, I ended up creating another .autorun script for turning on the swap. Works great!
  15. rhester72

    rhester72 Network Guru Member

    I just tried and utterly failed to get the "real" swapon (from util-linux) going. uClibc is *SO* frustratingly limiting at times. *sigh*

    Monk E. Boy, menses and koitsu like this.
  16. Monk E. Boy

    Monk E. Boy Network Guru Member

    The partition map this method creates is MBR, which means disks over 2TB in size will, at best, be limited to 2TB of total addressible space. Disks over 2TB should use a GPT partition map which Tomato can read but (as far as I'm aware) not create.

    If you have a disk over 2TB then you should use a desktop system to manipulate the partition map. A LiveCD/LiveUSB Linux distribution would work fine for any Windows users who just temporarily need the use of Linux.

    Sorry for bumping an old thread but someone recently linked to it, and he had a 5TB disk, so I thought an update was warranted.
    Madumi and ThanatosUA like this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice