UncheckpointableFilesystems
Contents |
Summary
Any task with an open filesystem object which does not support checkpoint through its .checkpoint file_operation (file, dir, etc) will cause sys_checkpoint() to return failure. Using the glibc syscall wrapper it would return -1 and set errno to EINVAL. Though some portions of a checkpoint image may exist, it's terminated with an "error" description so that any attempt to use it will cause restart to report failure.
Unsupported Files
The file_operations structs missing the .checkpoint operation can be found in (expanded fs/):
140 arch 3 block 1 crypto 1 Documentation 602 drivers 170 fs 3 9p 8 afs 1 autofs 3 autofs4 1 bad_inode.c 1 binfmt_misc.c 1 binfmt_misc.c 1 binfmt_misc.c 1 block_dev.c 2 cachefiles 1 char_dev.c 15 cifs 4 coda 2 configfs 3 debugfs 8 dlm 2 ext4 1 fifo.c 1 filesystems.c 2 fscache 7 fuse 5 gfs2 1 hugetlbfs 2 jbd2 6 jfs 1 libfs.c 1 locks.c 2 ncpfs 2 nfs 4 nfsd 1 no-block.c 1 notify 1 ntfs 15 ocfs2 53 proc 1 reiserfs 2 smbfs 3 sysfs 1 include 3 ipc 83 kernel 3 lib 12 mm 153 net 2 samples 34 security 28 sound 4 virt
(As of 2.6.31 + ckpt-v18-dev on Nov 16th, 2009)
Notes:
- The missing checkpoint file operation in fs/fifo.c is only an artifact of the way fifo file ops are assigned. FIFOs are supported.
Feel free to find the specific locations of these structs and/or generate histograms for your own tree using the script below.
Script
A hackish script to run on the kernel source to find all of the files that do not support checkpoint:
#!/bin/bash # # Identify foo_operations structs missing the given operation. # # This is not a foolproof way to check for the operation because it assumes: # the .field = foo syntax is used (rather than the field: foo syntax or # positional assignment). # # no '};' will be seen until the end of the fops struct. I think this implies: # No structs embedded in fops # No anonymous functions in fops # No funky macro business in fops (e.g. ({ .. }) or do { .. } while(0)) # # This script breaks when it scans for file_operations missing operations: # ./net/mac80211/debugfs_key.c:31+242: # # Note that the fs/fifo.c def_fifo_fops is "special" in that it's used # to "bootstrap" to the correct file operations struct, so it's missing # lots of ops you might expect even from a fifo. # DO_STAT="" DO_DUMP="" STRUCT=file_operations OP="checkpoint" KDIRS=( ) options=`getopt -o 'ao:d:s:v' --long 'auto-dirs,operation:,dir:,stat:,struct:,verbose' -- "$@"` eval set -- "$options" while true do case "$1" in --) shift break ;; --stat|-s) DO_STAT=$(( $2 + 0 )) DO_DUMP="" shift 2 ;; --verbose|-v) DO_DUMP=":" shift ;; --struct) STRUCT="$2" shift 2 ;; --operation|-o) OP="$2" shift 2 ;; --dir|-d) KDIRS+=("$2") shift 2 ;; --auto-dirs|-a) KDIRS+=( $(find ./ -mindepth 1 -maxdepth 1 -type d '!' -name '.git' -printf ' %p ') ) shift 1 ;; esac done KDIRS+=( "$@" ) if (( ${#KDIRS[@]} < 1 )); then exit 0 fi LIST=`mktemp check_fsop.XXXXX` trap "rm -f \"${LIST}\" ; exit 23" EXIT ERR rgrep -nHE 'struct[[:space:]]+'"${STRUCT}" "${KDIRS[@]}" | grep -v 'extern' | grep -v '\&' | grep -v 'sizeof' | grep '=' | grep -vE '[[:space:]]*=[[:space:]]*NULL[[:space:]]*;' > "${LIST}" || exit -1 ( for ENTRY in $(cat "${LIST}" | cut -d : -f 1,2) ; do FILE=$(echo "${ENTRY}" | cut -d : -f 1) START_FOPS=$(($(echo "${ENTRY}" | cut -d : -f 2) + 0)) LEN_FOPS=$(($(tail -n "+${START_FOPS}" "${FILE}" | grep -m 1 -nE '}' | cut -d : -f 1) + 0)) if [ -z "${LEN_FOPS}" ]; then continue fi ((LEN_FOPS + 0)) || continue tail -n "+${START_FOPS}" "${FILE}" | \ head -n ${LEN_FOPS} | \ grep -m 1 -E '\.'"${OP}" > /dev/null && continue echo "${FILE}:${START_FOPS}+${LEN_FOPS}${DO_DUMP}" if [ "${DO_DUMP}" == ":" ]; then cat -n "${FILE}" | tail -n "+${START_FOPS}" | head -n "${LEN_FOPS}" fi done ) | ( if [ -n "${DO_STAT}" ]; then cat - | cut -d / -f ${DO_STAT} | sort | uniq -c else cat - fi )