There are at least following reasons for this:
Considering the ioctl name, looks like the speed is only guaranteed not to be greater than the value requested.
Due to some confusings in the Broadcom datasheets, the older SPI driver spi-bcm2708 calculated the clock multiplier to be power of two instead of multiply of two. So the range of possible values was strongly reduced. This should be ok in the current driver spi-bcm2835. Check the current module loaded via lsmod.
Not sure why, but the SPI clock depends on the CPU clock. At least on my raspbian system, using the spi-bcm2835 driver, the real clock frequency meets the expectations on full speed only (1GHz). At the default idle speed (700MHz) the SPI clock is lower (e.g. 12.5MHz real for 20MHz request). Check/change the current CPU speed settings:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor #current policy
echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor #max performance
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq #min CPU clock frequency
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq #current CPU clock frequency
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq #max CPU clock frequency
EDIT:
After some more research, regarding the overclocking, following parameters in /boot/config.txt affect the SPI clock. Using the values provided the real timing meets the expectations.
arm_freq=700
arm_freq_min=700 #effectively disable scaling
core_freq=200 #not sure about exact meaning, but this allows precise SPI clock setup
core_freq_min=200
There is a tool able to determine either configured or real clock values of the overclocking parameters:
vcgencmd get_config arm_freq
vcgencmd get_config core_freq
vcgencmd measure_clock arm
vcgencmd measure_clock core
So the overclocked system in full performance mode (correct SPI setting) is 1000(arm)/400(core)MHz.
Nice summary for raspberry pi config options