Most of the Open Source backup software that I am aware of that does incremental backups (including backuppc, which I use) re-creates the entire directory structure for each increment. Copies of files with mulitple identical copies are then hard-linked together so that there is only one copy on disk, with obvious savings in disk usage.
This post points out that as the amount of stuff being backed up increases, an fsck on the partition in question can start taking a *very* long time, perhaps even running out of memory.
I have not even noticed, because I did not place my backuppc archive on the root partition. And it is only the root partition that occasionally experiences an automatic fsck on boot. Generally speaking, for better or worse, I simply never fsck non-root partitions without good reason, and Linux seems to give me very little of such "good reason". I am inclined to say this seems to be more of a hypothetical then a real problem, and until I actually see evidence of breakage I am not going to worry about it.
The biggest and oldest expat-oriented site in Beijing. Especially
good for their classified listings:
Another recent addition to the list of Beijing expat sites. Well-done
but will it succeed?:
Beijing bus routes. All Chinese, but is there any other way?:
Haidian Hospital: Clean, fast, cheap, professional service. But not a
word of English anywhere:
United Family Hospital: Probably the best hospital in Beijing.
Expensive, spacious, staffed by Australian doctors. A friend of mine had
major surgery (collar-bone reconstruction with plates and pins) and had
a first class experience:
I used to think Firefox was pretty fast, but that starts to become a long time ago.... Until I installed the Flashblock plugin.
With flashblock installed, the flash content on web pages is blocked and displayed as an empty square with an "f" button in the middle. If you really want to see the useless advertisement or graphic in the flash, just click on the "f".
After installing flashblock, it has suddenly become obvious how pervasive (and destructive to surfing speed) flash content has become. It seems to be everywhere, and as far as I can tell, the content is universally uninteresting. Certainly not worth the performance hit.
Flash bites you in two places. The obvious one is bandwidth. Flash objects tend to chew up a lot. With flash blocked, many web pages with several flash objects download in a fraction of the time. (This is particularly critical here in the bandwidth-starved part of the world, which tends to be most places outside of N.America and Europe....)
The second place the flash bites you is in the CPU, particularly if you have a somewhat older / slower machine. Flash objects tend to be resource hogs and will make your browser slower, and even appear to slow down your whole machine if you leave some flash running in your browser while you go and do some other things.
For the past little while cron on my laptop has been completely broken, with cron dumping an endless succession of segfaults (Segmentation Faults -- program attempts to access a forbidden area of memory) to the syslog. Since there was no apparent movement in the bug report, I set about trying to do something about it.
First I ran strace and ltrace on cron to see if it was failing for some kind of obvious reason: no luck, nothing interesting in the output.
Next thing to try: isolate exactly what line of code was failing using GDB.
First build, install, and restart a debug version of cron and libpam-mount (otherwise gdb output will just be a mess of numbers). Then start "gdb" in a root terminal (cron runs as root) and at the gdb prompt, attach to the running cron:
(gdb) attach 3489 Attaching to process 3489 Reading symbols from /usr/sbin/cron...done. Reading symbols from /lib/libpam.so.0...done. Loaded symbols for /lib/libpam.so.0 Reading symbols from /lib/libselinux.so.1...done. Loaded symbols for /lib/libselinux.so.1 Reading symbols from /lib/i686/cmov/libc.so.6...done. Loaded symbols for /lib/i686/cmov/libc.so.6 Reading symbols from /lib/i686/cmov/libdl.so.2...done. Loaded symbols for /lib/i686/cmov/libdl.so.2 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 Reading symbols from /lib/i686/cmov/libnss_compat.so.2...done. Loaded symbols for /lib/i686/cmov/libnss_compat.so.2 Reading symbols from /lib/i686/cmov/libnsl.so.1...done. Loaded symbols for /lib/i686/cmov/libnsl.so.1 Reading symbols from /lib/i686/cmov/libnss_nis.so.2...done. Loaded symbols for /lib/i686/cmov/libnss_nis.so.2 Reading symbols from /lib/i686/cmov/libnss_files.so.2...done. Loaded symbols for /lib/i686/cmov/libnss_files.so.2 0xb7f5e424 in __kernel_vsyscall ()
where the number after "attach" is the pid (process id) of cron (obtainable by running "ps -ef | grep cron"). Then:
(gdb) set follow-fork-mode child (gdb) cont Continuing.
The follow-fork-mode parameter has to be set to "child" because cron is in the habit of spawning child processes, and it is in the child process where the error occurs. Then let cron (frozen at the moment of the "attach") continue running with "cont". And wait for a segfault:
Continuing. Program received signal SIGSEGV, Segmentation fault. [Switching to process 19892] 0x00000000 in ?? () (gdb)
Now dump out some interesting information about the error:
(gdb) info frame 0 Stack frame at 0xbfba1aa0: eip = 0x0; saved eip 0xb7b4cda1 called by frame at 0xbfba1af0 Arglist at 0xbfba1a98, args: Locals at 0xbfba1a98, Previous frame's sp is 0xbfba1aa0 Saved registers: eip at 0xbfba1a9c (gdb) up #1 0xb7b4cda1 in read_password (pamh=0x8841b00, prompt=0x8846278 "reenter password for pam_mount:", pass=0xbfba1b38) at pam_mount.c:160 160 retval = conv->conv(nargs, message, resp, conv->appdata_ptr); (gdb) up #2 0xb7b4ddf3 in pam_sm_open_session (pamh=0x8841b00, flags=32768, argc=1, argv=0x8843ce0) at pam_mount.c:511 511 ret = read_password(pamh, Config.msg_sessionpw, &system_authtok); (gdb) up #3 0xb7f693c1 in _pam_dispatch (pamh=0x8841b00, flags=32768, choice=4) at pam_dispatch.c:108 108 retval = h->func(pamh, flags, h->argc, h->argv); (gdb) up #4 0xb7f6cfeb in pam_open_session (pamh=0x8841be8, flags=32768) at pam_session.c:23 23 retval = _pam_dispatch(pamh, flags, PAM_OPEN_SESSION); (gdb) up #5 0x0804e848 in child_process (e=0x88418f8, u=0x88418d8) at ../do_command.c:228 228 retcode = pam_open_session(pamh, PAM_SILENT); (gdb) up #6 0x0804e36d in do_command (e=0x88418f8, u=0x88418d8) at ../do_command.c:102 102 child_process(e, u); (gdb) up #7 0x0804e1e3 in job_runqueue () at ../job.c:68 68 do_command(j->e, j->u); (gdb) up #8 0x0804a777 in main (argc=142875624, argv=0x0) at ../cron.c:270 270 job_runqueue(); (gdb) up Initial frame selected; you cannot go up.
Above I used the "up" and "down" commands to step through the bugtrace and see the stack of procedure calls (and which line in each procedure) that was happening at the moment of the segfault. From this we can divine that the problem seems to happen in libpam-mount, specifically in pam_mount.c:160 of frame #2. (Note that frame 0 is a mess of numbers without symbolic information, because the piece of software coinciding with frame 0 has not been compiled with debug.)
(gdb) frame 0 #0 0x00000000 in ?? () (gdb) up #1 0xb7b4cda1 in read_password (pamh=0x8841b00, prompt=0x8846278 "reenter password for pam_mount:", pass=0xbfba1b38) at pam_mount.c:160 160 retval = conv->conv(nargs, message, resp, conv->appdata_ptr); (gdb) print *resp Cannot access memory at address 0x0 (gdb) print resp $3 = (struct pam_response *) 0x0 (gdb)
Above I used the "print" command to show the values the pointer *resp, which turns out to still be set to NULL, and is being passed on to another procedure (frame 0) which barfs. This is the likely problem.
I issued a bug report against libpam-mount suggesting a simple patch (which turned out to have bad side effects....) which prompted another developer to jump in and document an existing patch already applied to upstream. The fix is on the way....
Downloading, building, tweaking, and rebuilding a source tarball is not that difficult a concept for me at this point. Debian, however, has a very sophisticated (complex? obtuse? But I still love Debian....) packaging system.
Quick & Dirty Method:
Say I am trying to debug something with the cron package:
apt-get build-dep cron cd /to/where/you/want/to/install/your/source apt-get source cron cd cron-3.0 modify the code DEB_BUILD_OPTIONS=debug,nostrip fakeroot debian/rules binary debi
where dpkg-buildpackage builds a .deb and places it one directory up and debi installs the package. DEB_BUILD_OPTIONS are optional, but extremely useful if you are going to use gdb for debugging.
Note that the package version is not changed with this method, and the next time you run "apt-get upgrade" it will want to replace your debug version of the package with the repository version.
Patches & Versioning:
Sorting out how to mess with source code using the "Debian way" is not at all transparent. Roberto Sanchez' "Debian Package Customization HOWTO" is better:
Suppose someone sends you a patch that you want to test. Here is how you would obtain, patch, and build the source to create a new .deb with a unique version number, ready for installation:
apt-get source foo cd foo-1.0 patch -p0 < /path/to/patch/file/ # apply patch to source debchange -nmu # See note below sudo apt-get build-dep foo # install build dependencies dpkg-buildpackage # build binary package from source
"debchange -nmu" will bring up the changelog in your default editor. In addition to modifying the text of the log, it is also possible to modify the package version number in the header of the changelog entry. Sanchez recommends decrementing the version, adding a ".0.0" to the end, then adding a "name.0" to that. "name.0" is the part you use locally to track local changes. The preceding decremented-version.0.0 tries to ensure that any packages that appear in the repository afterwards will take precedence over the local package, so that upstream updates get installed (assuming that is what you want).
You should find your new .deb one directory up (..) with the version number as specified in the changelog.
Note that you might optionally want to put the source under the control of the git revision control system if you are going to make modifications yourself and submit patches.