BTW, the current description I've got next to struct fdtable definition: /* * fdtable's capacity is stored in ->max_fds; it is set when instance is * created and never changed after that. It is always a positive multiple * of BITS_PER_LONG (i.e. no less than BITS_PER_LONG). It can't exceed * MAX_INT - userland often stores descriptors as int, treating anything * negative as an error, so the numbers past MAX_INT are definitely * not usable as descriptors. * * if fdt->max_fds is equal to N, fdt can hold descriptors in range 0..N-1. * * ->fd points to an N-element array of file pointers. If descriptor #k is * open, ->fd[k] points to the file associated it; otherwise it's NULL. * * both ->open_fds and ->close_on_exec point to N-bit bitmaps. * Since N is a multiple of BITS_PER_LONG, those are arrays of unsigned long * with N / BITS_PER_LONG elements and all bits are in use. * Bit #k in ->open_fds is set iff descriptor #k has been claimed. * In that case the corresponding bit in ->close_on_exec determines whether * it should be closed on execve(). If descriptor is *not* claimed, the * value of corresponding bit in ->close_on_exec is undetermined. * * ->full_fds_bits points to a N/BITS_PER_LONG-bit bitmap, i.e. to an array of * unsigned long with BITS_TO_LONGS(N / BITS_PER_LONG) elements. Note that * N is *not* promised to be a multiple of BITS_PER_LONG^2, so there may be * unused bits in the last word. Its contents is a function of ->open_fds - * bit #k is set in it iff all bits stored in ->open_fds[k] are set (i.e. if * ->open_fds[k] == ~0ul). All unused bits in the last word must be clear. * That bitmap is used for cheaper search for unclaimed descriptors. * * Note that all of those are pointers - arrays themselves are elsewhere. * The whole thing is reached from a files_struct instance; the reason * we do not keep those pointers in files_struct itself is that on resize * we want to flip all of them at once *and* we want the readers to be * able to work locklessly. This is a device for switching all of those * in one store operation. Freeing the replaced instance is RCU-delayed; * ->rcu is used to do that. */