Salts must be unique; that's their one and only job. You should strive, as much as possible, to never reuse a salt value; the occasional reuse is rarely critical but should still be avoided). With reasonably designed password schemes, there is no other useful property in salts besides uniqueness; you can choose them however you want as long as you do not reproduce the exact same sequence of bits. Uniqueness must be understood worldwide.
(With badly designed password hashing schemes, the salt might have some required additional properties, but if you use a badly design password scheme you already have bigger problems. Note that a salt is not exactly the same as an Initialization Vector for symmetric encryption, where strict requirements like unpredictable uniform randomness typically apply.)
A common way to have more-or-less unique salt values is to generate them randomly, with a good generator (say, one which is fit for cryptographic usages, like /dev/urandom
). If the salt is long enough, risks of collisions (i.e. reusing a salt value) are low. If you use n-bit salts, chances of a collision become non-negligible once you reach about 2n/2 generated values. There are about 7 billions people on this planet, and it seems safe to assume that they, on average, own less than 1000 passwords each, so the worldwide number of hashed passwords must be somewhat lower than 242.7. Therefore, 86 bits of salt ought to be enough. Since we kind of like so-called "security margins", and, moreover, since programmers just love powers of two, let's go to 128 bits. As per the analysis above, that's more than enough to ensure worldwide uniqueness with high enough probability, and there is nothing more we want from a salt than uniqueness.
Uniqueness can also be ensured through other means, e.g. using as salt the concatenation of the server name (the worldwide DNS system already ensures that everybody can get his own server name, distinct from that of anybody else on the planet) and a server-wide counter. This raises some practical issues, e.g. maintaining a counter value which does not repeat, even in the case of an ill-timed server crash&reboot, and/or several front-ends with load balancing. A random fixed-length salt is easier.