Code review comment: Let's stick with the `Deadline` as in your proposal there is already a small bug (for the timeout based on subtraction to work, you would have to subtract it only if `segment == null`, otherwise even if get the buffer after only a 1 millisecond of waiting, you subtract 2 seconds of waiting time).

Code under review:
public List<MemorySegment> requestMemorySegments() throws IOException {
		synchronized (factoryLock) {
			if (isDestroyed) {
				throw new IllegalStateException("Network buffer pool has already been destroyed.");
			}

			if (numTotalRequiredBuffers + numberOfSegmentsToRequest > totalNumberOfMemorySegments) {
				throw new IOException(String.format("Insufficient number of network buffers: " +
								"required %d, but only %d available. The total number of network " +
								"buffers is currently set to %d of %d bytes each. You can increase this " +
								"number by setting the configuration keys '%s', '%s', and '%s'.",
					numberOfSegmentsToRequest,
						totalNumberOfMemorySegments - numTotalRequiredBuffers,
						totalNumberOfMemorySegments,
						memorySegmentSize,
						NettyShuffleEnvironmentOptions.NETWORK_BUFFERS_MEMORY_FRACTION.key(),
						NettyShuffleEnvironmentOptions.NETWORK_BUFFERS_MEMORY_MIN.key(),
						NettyShuffleEnvironmentOptions.NETWORK_BUFFERS_MEMORY_MAX.key()));
			}

			this.numTotalRequiredBuffers += numberOfSegmentsToRequest;

			try {
				redistributeBuffers();
			} catch (Throwable t) {
				this.numTotalRequiredBuffers -= numberOfSegmentsToRequest;

				try {
					redistributeBuffers();
				} catch (IOException inner) {
					t.addSuppressed(inner);
				}
				ExceptionUtils.rethrowIOException(t);
			}
		}

		final List<MemorySegment> segments = new ArrayList<>(numberOfSegmentsToRequest);
		try {
			final Deadline deadline = Deadline.now().plus(Duration.ofMillis(requestSegmentsTimeoutInMillis));
			while (true) {
				if (isDestroyed) {
					throw new IllegalStateException("Buffer pool is destroyed.");
				}

				final MemorySegment segment = availableMemorySegments.poll(2, TimeUnit.SECONDS);
				if (segment != null) {
					segments.add(segment);
				}

				if (segments.size() >= numberOfSegmentsToRequest) {
					break;
				}

				if (!deadline.hasTimeLeft()) {
					throw new IOException(String.format("Insufficient number of network buffers: " +
									"requesting exclusive buffers timeout. The total number of network " +
									"buffers is currently set to %d of %d bytes each. You can increase this " +
									"number by setting the configuration keys '%s', '%s', and '%s'.",
							totalNumberOfMemorySegments,
							memorySegmentSize,
							NettyShuffleEnvironmentOptions.NETWORK_BUFFERS_MEMORY_FRACTION.key(),
							NettyShuffleEnvironmentOptions.NETWORK_BUFFERS_MEMORY_MIN.key(),
							NettyShuffleEnvironmentOptions.NETWORK_BUFFERS_MEMORY_MAX.key()));
				}
			}
		} catch (Throwable e) {
			try {
				recycleMemorySegments(segments, numberOfSegmentsToRequest);
			} catch (IOException inner) {
				e.addSuppressed(inner);
			}
			ExceptionUtils.rethrowIOException(e);
		}

		return segments;
	}

Line commented on: final Deadline deadline = Deadline.now().plus(Duration.ofMillis(requestSegmentsTimeoutInMillis));

Revised code:
public List<MemorySegment> requestMemorySegments() throws IOException {
		synchronized (factoryLock) {
			if (isDestroyed) {
				throw new IllegalStateException("Network buffer pool has already been destroyed.");
			}

			tryRedistributeBuffers();
		}

		final List<MemorySegment> segments = new ArrayList<>(numberOfSegmentsToRequest);
		try {
			final Deadline deadline = Deadline.fromNow(requestSegmentsTimeout);
			while (true) {
				if (isDestroyed) {
					throw new IllegalStateException("Buffer pool is destroyed.");
				}

				final MemorySegment segment = availableMemorySegments.poll(2, TimeUnit.SECONDS);
				if (segment != null) {
					segments.add(segment);
				}

				if (segments.size() >= numberOfSegmentsToRequest) {
					break;
				}

				if (!deadline.hasTimeLeft()) {
					throw new IOException(String.format("Timeout triggered when requesting exclusive buffers: %s, " +
									" or you may increase the timeout which is %dms by setting the key '%s'.",
							getConfigDescription(),
							requestSegmentsTimeout.toMillis(),
							NettyShuffleEnvironmentOptions.NETWORK_EXCLUSIVE_BUFFERS_REQUEST_TIMEOUT_MILLISECONDS.key()));
				}
			}
		} catch (Throwable e) {
			try {
				recycleMemorySegments(segments, numberOfSegmentsToRequest);
			} catch (IOException inner) {
				e.addSuppressed(inner);
			}
			ExceptionUtils.rethrowIOException(e);
		}

		return segments;
	}