Console freezes on auto-complete of /mnt/folder (CIFS) share

Solution 1:

This has to do with both the way bash completion works and the way cifs works as a protocol.

bash completion works thusly:

  1. readline informs bash of the currently-typed string, and of the tab keystroke.
  2. bash performs a Depth First Searchof the filesystem, the root of which is at the most-matched part of the filesystem hierarchy. Each step of this search is actually many requests - a request for a list - from the filesystem.
  3. readline blocks - waiting for a response from bash with a list of possible outcomes to display.
  4. that list arrives, readline displays it, and returns input control to the user.

On a blocklevel or local or otherwise reasonably-fast filesystem, this all happens incredibly quickly.

CIFS, unfortunately, isn't a blocklevel filesystem. Instead, CIFS is a command-based transactional protocol. Every single request made against CIFS is:

  • transactional, requiring a request, acknowledgement, and acknowledgement of the acknowledgement,
  • represented by multiple individual CIFS/SMB command blocks
  • inspected for authentication

In short, CIFS/SMB is (at least in SMB1, which almost assuredly is what you're using to mount this CIFS share) extremely chatty.

In ordinary, direct usage of known filenames, the request is a singleton. You make the request for a file, CIFS authenticates you, acknowledges your request, you acknowledge their acknowledgement, and your file transfers.

In the case of tab-completion, that cycle is multiplied by the number of files in a particular directory, possibly times two (or more!) if it's dereferencing a Windows Shortcut.

All over the network.

This is a recipe for significant slowdowns as readline waits for bash who's in turn waiting for the filesystem driver to negotiate with the CIFS server.

You may wish to work around this problem by doing things like running your session from within screen, that way if your bash session locks up, you can ctrl-A-c and get s brand spanking new terminal, so you can continue to work or even kill the other one.