Index: uspace/srv/bd/hr/util.c
===================================================================
--- uspace/srv/bd/hr/util.c	(revision f7257870f3b7481e23d50317fe1f7d861207f733)
+++ uspace/srv/bd/hr/util.c	(revision 38e3c0a71c979f993a92692cc2238b2abbdbc386)
@@ -34,6 +34,8 @@
  */
 
+#include <adt/list.h>
 #include <block.h>
 #include <errno.h>
+#include <fibril_synch.h>
 #include <hr.h>
 #include <io/log.h>
@@ -46,4 +48,10 @@
 #include "var.h"
 
+#define HR_RL_LIST_LOCK(vol) (fibril_mutex_lock(&vol->range_lock_list_lock))
+#define HR_RL_LIST_UNLOCK(vol) \
+    (fibril_mutex_unlock(&vol->range_lock_list_lock))
+
+static bool hr_range_lock_overlap(hr_range_lock_t *, hr_range_lock_t *);
+
 extern loc_srv_t *hr_srv;
 
@@ -128,5 +136,4 @@
 
 	vol->svc_id = new_id;
-
 error:
 	free(fullname);
@@ -258,12 +265,102 @@
 {
 	size_t count = 0;
-	for (size_t i = 0; i < vol->extent_no; i++) {
+	for (size_t i = 0; i < vol->extent_no; i++)
 		if (vol->extents[i].status == status)
 			count++;
-	}
 
 	return count;
 }
 
+hr_range_lock_t *hr_range_lock_acquire(hr_volume_t *vol, uint64_t ba,
+    uint64_t cnt)
+{
+	hr_range_lock_t *rl = malloc(sizeof(hr_range_lock_t));
+	if (rl == NULL)
+		return NULL;
+
+	rl->vol = vol;
+	rl->off = ba;
+	rl->len = cnt;
+
+	rl->pending = 1;
+	rl->ignore = false;
+
+	link_initialize(&rl->link);
+	fibril_mutex_initialize(&rl->lock);
+
+	fibril_mutex_lock(&rl->lock);
+
+again:
+	HR_RL_LIST_LOCK(vol);
+	list_foreach(vol->range_lock_list, link, hr_range_lock_t, rlp) {
+		if (rlp->ignore)
+			continue;
+		if (hr_range_lock_overlap(rlp, rl)) {
+			rlp->pending++;
+
+			HR_RL_LIST_UNLOCK(vol);
+
+			fibril_mutex_lock(&rlp->lock);
+
+			HR_RL_LIST_LOCK(vol);
+
+			rlp->pending--;
+
+			/*
+			 * when ignore is set, after HR_RL_LIST_UNLOCK(),
+			 * noone new is going to be able to start sleeping
+			 * on the ignored range lock, only already waiting
+			 * IOs will come through here
+			 */
+			rlp->ignore = true;
+
+			fibril_mutex_unlock(&rlp->lock);
+
+			if (rlp->pending == 0) {
+				list_remove(&rlp->link);
+				free(rlp);
+			}
+
+			HR_RL_LIST_UNLOCK(vol);
+			goto again;
+		}
+	}
+
+	list_append(&rl->link, &vol->range_lock_list);
+
+	HR_RL_LIST_UNLOCK(vol);
+	return rl;
+}
+
+void hr_range_lock_release(hr_range_lock_t *rl)
+{
+	HR_RL_LIST_LOCK(rl->vol);
+
+	rl->pending--;
+
+	fibril_mutex_unlock(&rl->lock);
+
+	if (rl->pending == 0) {
+		list_remove(&rl->link);
+		free(rl);
+	}
+
+	HR_RL_LIST_UNLOCK(rl->vol);
+}
+
+static bool hr_range_lock_overlap(hr_range_lock_t *rl1, hr_range_lock_t *rl2)
+{
+	uint64_t rl1_start = rl1->off;
+	uint64_t rl1_end = rl1->off + rl1->len - 1;
+	uint64_t rl2_start = rl2->off;
+	uint64_t rl2_end = rl2->off + rl2->len - 1;
+
+	/* one ends before the other starts */
+	if (rl1_end < rl2_start || rl2_end < rl1_start)
+		return false;
+
+	return true;
+}
+
 /** @}
  */
Index: uspace/srv/bd/hr/util.h
===================================================================
--- uspace/srv/bd/hr/util.h	(revision f7257870f3b7481e23d50317fe1f7d861207f733)
+++ uspace/srv/bd/hr/util.h	(revision 38e3c0a71c979f993a92692cc2238b2abbdbc386)
@@ -61,4 +61,7 @@
 extern void hr_sync_all_extents(hr_volume_t *);
 extern size_t hr_count_extents(hr_volume_t *, hr_ext_status_t);
+extern hr_range_lock_t *hr_range_lock_acquire(hr_volume_t *, uint64_t,
+    uint64_t);
+extern void hr_range_lock_release(hr_range_lock_t *rl);
 
 #endif
Index: uspace/srv/bd/hr/var.h
===================================================================
--- uspace/srv/bd/hr/var.h	(revision f7257870f3b7481e23d50317fe1f7d861207f733)
+++ uspace/srv/bd/hr/var.h	(revision 38e3c0a71c979f993a92692cc2238b2abbdbc386)
@@ -37,6 +37,8 @@
 #define _HR_VAR_H
 
+#include <adt/list.h>
 #include <bd_srv.h>
 #include <errno.h>
+#include <fibril_synch.h>
 #include <hr.h>
 
@@ -60,4 +62,7 @@
 	link_t lvolumes;
 	fibril_mutex_t lock;
+
+	list_t range_lock_list;
+	fibril_mutex_t range_lock_list_lock;
 
 	size_t extent_no;
@@ -90,4 +95,14 @@
 } hr_bd_op_type_t;
 
+typedef struct hr_range_lock {
+	fibril_mutex_t lock;
+	link_t link;
+	hr_volume_t *vol;
+	uint64_t off;
+	uint64_t len;
+	size_t pending; /* protected by vol->range_lock_list_lock */
+	bool ignore; /* protected by vol->range_lock_list_lock */
+} hr_range_lock_t;
+
 extern errno_t hr_init_devs(hr_volume_t *);
 extern void hr_fini_devs(hr_volume_t *);
