Index: uspace/app/vol/vol.c
===================================================================
--- uspace/app/vol/vol.c	(revision db9c88924815f5224f632a9114b5427633cf77dc)
+++ uspace/app/vol/vol.c	(revision 72c72d4a367ffdd08c3e7633b0240d085bd83925)
@@ -52,5 +52,89 @@
 } vol_cmd_t;
 
-static int vol_cmd_list(void)
+/** Find volume by current mount point. */
+static errno_t vol_cmd_part_by_mp(vol_t *vol, const char *mp,
+    service_id_t *rid)
+{
+	vol_part_info_t vinfo;
+	service_id_t *part_ids = NULL;
+	char *canon_mp_buf = NULL;
+	char *canon_mp;
+	size_t nparts;
+	size_t i;
+	errno_t rc;
+
+	canon_mp_buf = str_dup(mp);
+	if (canon_mp_buf == NULL) {
+		printf("Out of memory.\n");
+		rc = ENOMEM;
+		goto out;
+	}
+
+	canon_mp = vfs_absolutize(canon_mp_buf, NULL);
+	if (canon_mp == NULL) {
+		printf("Invalid volume path '%s'.\n", mp);
+		rc = EINVAL;
+		goto out;
+	}
+
+	rc = vol_get_parts(vol, &part_ids, &nparts);
+	if (rc != EOK) {
+		printf("Error getting list of volumes.\n");
+		goto out;
+	}
+
+	for (i = 0; i < nparts; i++) {
+		rc = vol_part_info(vol, part_ids[i], &vinfo);
+		if (rc != EOK) {
+			printf("Error getting volume information.\n");
+			rc = EIO;
+			goto out;
+		}
+
+		if (str_cmp(vinfo.cur_mp, canon_mp) == 0) {
+			*rid = part_ids[i];
+			rc = EOK;
+			goto out;
+		}
+	}
+
+	rc = ENOENT;
+out:
+	free(part_ids);
+	free(canon_mp_buf);
+	return rc;
+}
+
+static errno_t vol_cmd_eject(const char *volspec)
+{
+	vol_t *vol = NULL;
+	service_id_t part_id;
+	errno_t rc;
+
+	rc = vol_create(&vol);
+	if (rc != EOK) {
+		printf("Error contacting volume service.\n");
+		goto out;
+	}
+
+	rc = vol_cmd_part_by_mp(vol, volspec, &part_id);
+	if (rc != EOK) {
+		printf("Error looking up volume '%s'.\n", volspec);
+		goto out;
+	}
+
+	rc = vol_part_eject(vol, part_id);
+	if (rc != EOK) {
+		printf("Error ejecting volume.\n");
+		goto out;
+	}
+
+	rc = EOK;
+out:
+	vol_destroy(vol);
+	return rc;
+}
+
+static errno_t vol_cmd_list(void)
 {
 	vol_t *vol = NULL;
@@ -62,5 +146,5 @@
 	size_t i;
 	table_t *table = NULL;
-	int rc;
+	errno_t rc;
 
 	rc = vol_create(&vol);
@@ -139,5 +223,5 @@
 	vol_cmd_t vcmd;
 	int i;
-	int rc;
+	errno_t rc;
 
 	if (argc < 2) {
@@ -169,5 +253,5 @@
 	switch (vcmd) {
 	case vcmd_eject:
-		rc = EOK;
+		rc = vol_cmd_eject(volspec);
 		break;
 	case vcmd_help:
Index: uspace/lib/c/generic/vol.c
===================================================================
--- uspace/lib/c/generic/vol.c	(revision db9c88924815f5224f632a9114b5427633cf77dc)
+++ uspace/lib/c/generic/vol.c	(revision 72c72d4a367ffdd08c3e7633b0240d085bd83925)
@@ -235,4 +235,20 @@
 }
 
+/** Unmount partition (and possibly eject the media). */
+errno_t vol_part_eject(vol_t *vol, service_id_t sid)
+{
+	async_exch_t *exch;
+	errno_t retval;
+
+	exch = async_exchange_begin(vol->sess);
+	retval = async_req_1_0(exch, VOL_PART_EJECT, sid);
+	async_exchange_end(exch);
+
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
 /** Erase partition (to the extent where we will consider it not containing
  * a file system.
Index: uspace/lib/c/include/ipc/vol.h
===================================================================
--- uspace/lib/c/include/ipc/vol.h	(revision db9c88924815f5224f632a9114b5427633cf77dc)
+++ uspace/lib/c/include/ipc/vol.h	(revision 72c72d4a367ffdd08c3e7633b0240d085bd83925)
@@ -42,7 +42,8 @@
 	VOL_PART_ADD,
 	VOL_PART_INFO,
+	VOL_PART_EJECT,
 	VOL_PART_EMPTY,
 	VOL_PART_LSUPP,
-	VOL_PART_MKFS,
+	VOL_PART_MKFS
 } vol_request_t;
 
Index: uspace/srv/volsrv/part.c
===================================================================
--- uspace/srv/volsrv/part.c	(revision db9c88924815f5224f632a9114b5427633cf77dc)
+++ uspace/srv/volsrv/part.c	(revision 72c72d4a367ffdd08c3e7633b0240d085bd83925)
@@ -478,8 +478,11 @@
 errno_t vol_part_get_info(vol_part_t *part, vol_part_info_t *pinfo)
 {
+	memset(pinfo, 0, sizeof(*pinfo));
+
 	pinfo->pcnt = part->pcnt;
 	pinfo->fstype = part->fstype;
 	str_cpy(pinfo->label, sizeof(pinfo->label), part->label);
-	str_cpy(pinfo->cur_mp, sizeof(pinfo->cur_mp), part->cur_mp);
+	if (part->cur_mp != NULL)
+		str_cpy(pinfo->cur_mp, sizeof(pinfo->cur_mp), part->cur_mp);
 	pinfo->cur_mp_auto = part->cur_mp_auto;
 	return EOK;
Index: uspace/srv/volsrv/volsrv.c
===================================================================
--- uspace/srv/volsrv/volsrv.c	(revision db9c88924815f5224f632a9114b5427633cf77dc)
+++ uspace/srv/volsrv/volsrv.c	(revision 72c72d4a367ffdd08c3e7633b0240d085bd83925)
@@ -181,4 +181,28 @@
 }
 
+static void vol_part_eject_srv(cap_call_handle_t icall_handle, ipc_call_t *icall)
+{
+	service_id_t sid;
+	vol_part_t *part;
+	errno_t rc;
+
+	sid = IPC_GET_ARG1(*icall);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_eject_srv(%zu)", sid);
+
+	rc = vol_part_find_by_id(sid, &part);
+	if (rc != EOK) {
+		async_answer_0(icall_handle, ENOENT);
+		return;
+	}
+
+	rc = vol_part_eject_part(part);
+	if (rc != EOK) {
+		async_answer_0(icall_handle, EIO);
+		return;
+	}
+
+	async_answer_0(icall_handle, EOK);
+}
+
 static void vol_part_empty_srv(cap_call_handle_t icall_handle, ipc_call_t *icall)
 {
@@ -314,4 +338,7 @@
 			vol_part_info_srv(chandle, &call);
 			break;
+		case VOL_PART_EJECT:
+			vol_part_eject_srv(chandle, &call);
+			break;
 		case VOL_PART_EMPTY:
 			vol_part_empty_srv(chandle, &call);
