nbd-server: handle modern-style negotiation in a child process

Previously, the modern style negotiation was carried out in the root
server (listener) process before forking the actual client handler. This
made it possible for a malfunctioning or evil client to terminate the
root process simply by querying a non-existent export or aborting in the
middle of the negotation process (caused SIGPIPE in the server).

This commit moves the negotiation process to the child to keep the root
process up and running no matter what happens during the negotiation.

See http://sourceforge.net/mailarchive/message.php?msg_id=30410146

Signed-off-by: Tuomas Räsänen <tuomasjjrasanen@tjjr.fi>
int exptrim(struct nbd_request* req, CLIENT* client) {
#if HAVE_FALLOC_PH
	FILE_INFO prev = g_array_index(client->export, FILE_INFO, 0);
	FILE_INFO cur = prev;
	int i = 1;
	/* We're running on a system that supports the
	 * FALLOC_FL_PUNCH_HOLE option to re-sparsify a file */
	do {
		if(i<client->export->len) {
			cur = g_array_index(client->export, FILE_INFO, i);
		}
		if(prev.startoff <= req->from) {
			off_t curoff = req->from - prev.startoff;
			off_t curlen = cur.startoff - prev.startoff - curoff;
			fallocate(prev.fhandle, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, curoff, curlen);
		}
		prev = cur;
	} while(i < client->export->len && cur.startoff < (req->from + req->len));
	DEBUG("Performed TRIM request from %llu to %llu", (unsigned long long) req->from, (unsigned long long) req->len);
#else
	DEBUG("Ignoring TRIM request (not supported on current platform");
#endif
	return 0;
}

int exptrim(struct nbd_request* req, CLIENT* client) {
#if HAVE_FALLOC_PH
	FILE_INFO prev = g_array_index(client->export, FILE_INFO, 0);
	FILE_INFO cur = prev;
	int i = 1;
	/* We're running on a system that supports the
	 * FALLOC_FL_PUNCH_HOLE option to re-sparsify a file */
	do {
		if(i<client->export->len) {
			cur = g_array_index(client->export, FILE_INFO, i);
		}
		if(prev.startoff <= req->from) {
			off_t curoff = req->from - prev.startoff;
			off_t curlen = cur.startoff - prev.startoff - curoff;
			fallocate(prev.fhandle, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, curoff, curlen);
		}
		prev = cur;
	} while(i < client->export->len && cur.startoff < (req->from + req->len));
	DEBUG("Performed TRIM request from %llu to %llu", (unsigned long long) req->from, (unsigned long long) req->len);
#else
	DEBUG("Ignoring TRIM request (not supported on current platform");
#endif
	return 0;
}
