This would be a straight proxy with no caching. One client request would correspond to one server request. If a module isn't required, it simply isn't called. This would reduce the stack depth you can end up with when processing a request. The connection manager creates an ftpservlet object and then attaches it to the clientlet it in its place.
All communication can happen now directly between the servlet and the clientlet.
It also should make the code a lot easier to manage and extend, and various new features such as content filtering could be implemented. A 'cache' could then be implemented by creating a cache-aware connection manager, which would probably be the storage manager. I think that when data is to be written to a client, as much data as possible should be attempted to write, and then if there is any left schedule a write select callback. Deferred reads do not work well inside an event-driven environment. There is no easy way in an event-driven IO system to tell whether a fd should be deferred at event register time.