changeset 12550:2c299c0e3bc8

lib-storage: Moved some items from mailbox_get_status() to a new mailbox_get_metadata(). The idea is now that all status items are tracked all the time after mailbox is opened and they can always be looked up without failure. The metadata items are looked up lazily and the lookups may fail at any time. mailbox_get_status() can be used after mailbox_alloc() to indicate that the mailbox doesn't necessarily have to be opened, just that the status fields get returned. If mailbox is already known to be open, mailbox_get_open_status() can be used. It never fails.
author Timo Sirainen <tss@iki.fi>
date Sat, 01 Jan 2011 15:52:39 +0200
parents bbfa924bc4bc
children 917f3699af5b
files src/doveadm/doveadm-mail-fetch.c src/doveadm/doveadm-mail-mailbox-status.c src/doveadm/doveadm-mail-search.c src/doveadm/doveadm-mail.c src/doveadm/doveadm-mail.h src/dsync/dsync-worker-local.c src/imap/cmd-enable.c src/imap/cmd-select.c src/imap/cmd-store.c src/imap/imap-client.c src/imap/imap-client.h src/imap/imap-commands-util.c src/imap/imap-fetch.c src/imap/imap-search.c src/imap/imap-status.c src/imap/imap-status.h src/imap/imap-sync.c src/lib-storage/index/dbox-multi/mdbox-storage.c src/lib-storage/index/dbox-single/sdbox-storage.c src/lib-storage/index/index-search.c src/lib-storage/index/index-status.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-storage.h src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/list/index-mailbox-list-sync.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h src/plugins/fts-solr/fts-backend-solr.c src/plugins/fts-squat/fts-backend-squat.c src/plugins/fts/fts-storage.c src/plugins/virtual/virtual-save.c src/plugins/virtual/virtual-storage.c src/plugins/virtual/virtual-sync.c src/pop3/pop3-client.c
diffstat 36 files changed, 401 insertions(+), 289 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/doveadm-mail-fetch.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/doveadm/doveadm-mail-fetch.c	Sat Jan 01 15:52:39 2011 +0200
@@ -63,11 +63,12 @@
 
 static int fetch_mailbox_guid(struct fetch_cmd_context *ctx)
 {
-	uint8_t guid[MAIL_GUID_128_SIZE];
+	struct mailbox_metadata metadata;
 
-	if (mailbox_get_guid(ctx->mail->box, guid) < 0)
+	if (mailbox_get_metadata(ctx->mail->box, MAILBOX_METADATA_GUID,
+				 &metadata) < 0)
 		return -1;
-	doveadm_print(mail_guid_128_to_string(guid));
+	doveadm_print(mail_guid_128_to_string(metadata.guid));
 	return 0;
 }
 
--- a/src/doveadm/doveadm-mail-mailbox-status.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/doveadm/doveadm-mail-mailbox-status.c	Sat Jan 01 15:52:39 2011 +0200
@@ -12,18 +12,24 @@
 #define ALL_STATUS_ITEMS \
 	(STATUS_MESSAGES | STATUS_RECENT | \
 	 STATUS_UIDNEXT | STATUS_UIDVALIDITY | \
-	 STATUS_UNSEEN | STATUS_HIGHESTMODSEQ | STATUS_VIRTUAL_SIZE)
+	 STATUS_UNSEEN | STATUS_HIGHESTMODSEQ)
+#define ALL_METADATA_ITEMS \
+	(MAILBOX_METADATA_VIRTUAL_SIZE | MAILBOX_METADATA_GUID)
 
 #define TOTAL_STATUS_ITEMS \
-	(STATUS_MESSAGES | STATUS_RECENT | STATUS_UNSEEN | STATUS_VIRTUAL_SIZE)
+	(STATUS_MESSAGES | STATUS_RECENT | STATUS_UNSEEN)
+#define TOTAL_METADATA_ITEMS \
+	(MAILBOX_METADATA_VIRTUAL_SIZE)
 
 struct status_cmd_context {
 	struct doveadm_mail_cmd_context ctx;
 	struct mail_search_args *search_args;
-	enum mailbox_status_items items;
+
+	enum mailbox_status_items status_items;
+	enum mailbox_metadata_items metadata_items;
 	struct mailbox_status total_status;
+	struct mailbox_metadata total_metadata;
 
-	unsigned int guid:1;
 	unsigned int total_sum:1;
 };
 
@@ -37,40 +43,42 @@
 		const char *field = *fields;
 
 		if (strcmp(field, "all") == 0) {
-			if (ctx->total_sum)
-				ctx->items |= TOTAL_STATUS_ITEMS;
-			else {
-				ctx->items |= ALL_STATUS_ITEMS;
-				ctx->guid = TRUE;
+			if (ctx->total_sum) {
+				ctx->status_items |= TOTAL_STATUS_ITEMS;
+				ctx->metadata_items |= TOTAL_METADATA_ITEMS;
+			} else {
+				ctx->status_items |= ALL_STATUS_ITEMS;
+				ctx->metadata_items |= ALL_METADATA_ITEMS;
 			}
 		} else if (strcmp(field, "messages") == 0)
-			ctx->items |= STATUS_MESSAGES;
+			ctx->status_items |= STATUS_MESSAGES;
 		else if (strcmp(field, "recent") == 0)
-			ctx->items |= STATUS_RECENT;
+			ctx->status_items |= STATUS_RECENT;
 		else if (strcmp(field, "uidnext") == 0)
-			ctx->items |= STATUS_UIDNEXT;
+			ctx->status_items |= STATUS_UIDNEXT;
 		else if (strcmp(field, "uidvalidity") == 0)
-			ctx->items |= STATUS_UIDVALIDITY;
+			ctx->status_items |= STATUS_UIDVALIDITY;
 		else if (strcmp(field, "unseen") == 0)
-			ctx->items |= STATUS_UNSEEN;
+			ctx->status_items |= STATUS_UNSEEN;
 		else if (strcmp(field, "highestmodseq") == 0)
-			ctx->items |= STATUS_HIGHESTMODSEQ;
+			ctx->status_items |= STATUS_HIGHESTMODSEQ;
 		else if (strcmp(field, "vsize") == 0)
-			ctx->items |= STATUS_VIRTUAL_SIZE;
+			ctx->metadata_items |= MAILBOX_METADATA_VIRTUAL_SIZE;
 		else if (strcmp(field, "guid") == 0)
-			ctx->guid = TRUE;
+			ctx->metadata_items |= MAILBOX_METADATA_GUID;
 		else
 			i_fatal("Unknown status field: %s", field);
 
 		if (ctx->total_sum &&
-		    ((ctx->items & ~TOTAL_STATUS_ITEMS) != 0 || ctx->guid))
+		    ((ctx->status_items & ~TOTAL_STATUS_ITEMS) != 0 ||
+		     (ctx->metadata_items & ~TOTAL_METADATA_ITEMS) != 0))
 			i_fatal("Status field %s can't be used with -t", field);
 	}
 }
 
 static void status_output(struct status_cmd_context *ctx, struct mailbox *box,
 			  const struct mailbox_status *status,
-			  uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
+			  const struct mailbox_metadata *metadata)
 {
 	string_t *name;
 
@@ -83,34 +91,35 @@
 		doveadm_print(str_c(name));
 	}
 
-	if ((ctx->items & STATUS_MESSAGES) != 0)
+	if ((ctx->status_items & STATUS_MESSAGES) != 0)
 		doveadm_print_num(status->messages);
-	if ((ctx->items & STATUS_RECENT) != 0)
+	if ((ctx->status_items & STATUS_RECENT) != 0)
 		doveadm_print_num(status->recent);
-	if ((ctx->items & STATUS_UIDNEXT) != 0)
+	if ((ctx->status_items & STATUS_UIDNEXT) != 0)
 		doveadm_print_num(status->uidnext);
-	if ((ctx->items & STATUS_UIDVALIDITY) != 0)
+	if ((ctx->status_items & STATUS_UIDVALIDITY) != 0)
 		doveadm_print_num(status->uidvalidity);
-	if ((ctx->items & STATUS_UNSEEN) != 0)
+	if ((ctx->status_items & STATUS_UNSEEN) != 0)
 		doveadm_print_num(status->unseen);
-	if ((ctx->items & STATUS_HIGHESTMODSEQ) != 0)
+	if ((ctx->status_items & STATUS_HIGHESTMODSEQ) != 0)
 		doveadm_print_num(status->highest_modseq);
-	if ((ctx->items & STATUS_VIRTUAL_SIZE) != 0)
-		doveadm_print_num(status->virtual_size);
-	if (ctx->guid)
-		doveadm_print(mail_guid_128_to_string(mailbox_guid));
+	if ((ctx->metadata_items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0)
+		doveadm_print_num(metadata->virtual_size);
+	if ((ctx->metadata_items & MAILBOX_METADATA_GUID) != 0)
+		doveadm_print(mail_guid_128_to_string(metadata->guid));
 }
 
 static void
 status_sum(struct status_cmd_context *ctx,
-	   const struct mailbox_status *status)
+	   const struct mailbox_status *status,
+	   const struct mailbox_metadata *metadata)
 {
 	struct mailbox_status *dest = &ctx->total_status;
 
 	dest->messages += status->messages;
 	dest->recent += status->recent;
 	dest->unseen += status->unseen;
-	dest->virtual_size += status->virtual_size;
+	ctx->total_metadata.virtual_size += metadata->virtual_size;
 }
 
 static void
@@ -118,7 +127,7 @@
 {
 	struct mailbox *box;
 	struct mailbox_status status;
-	uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+	struct mailbox_metadata metadata;
 	string_t *mailbox_name = t_str_new(128);
 
 	if (imap_utf7_to_utf8(info->name, mailbox_name) < 0) {
@@ -126,20 +135,17 @@
 		str_append(mailbox_name, info->name);
 	}
 
-	if (doveadm_mailbox_find_and_sync(ctx->ctx.cur_mail_user,
-					  str_c(mailbox_name), &box) < 0 ||
-	   mailbox_get_status(box, ctx->items, &status) < 0) {
+	box = doveadm_mailbox_find(ctx->ctx.cur_mail_user, str_c(mailbox_name));
+	if (mailbox_get_status(box, ctx->status_items, &status) < 0 ||
+	    mailbox_get_metadata(box, ctx->metadata_items, &metadata) < 0) {
 		ctx->ctx.failed = TRUE;
+		mailbox_free(&box);
 		return;
 	}
-	if (ctx->guid) {
-		if (mailbox_get_guid(box, mailbox_guid) < 0)
-			memset(mailbox_guid, 0, sizeof(mailbox_guid));
-	}
 	if (!ctx->total_sum)
-		status_output(ctx, box, &status, mailbox_guid);
+		status_output(ctx, box, &status, &metadata);
 	else
-		status_sum(ctx, &status);
+		status_sum(ctx, &status, &metadata);
 	mailbox_free(&box);
 }
 
@@ -165,8 +171,10 @@
 	}
 	doveadm_mail_list_iter_deinit(&iter);
 
-	if (ctx->total_sum)
-		status_output(ctx, NULL, &ctx->total_status, NULL);
+	if (ctx->total_sum) {
+		status_output(ctx, NULL, &ctx->total_status,
+			      &ctx->total_metadata);
+	}
 }
 
 static void cmd_mailbox_status_init(struct doveadm_mail_cmd_context *_ctx,
@@ -185,21 +193,21 @@
 		doveadm_print_header("mailbox", "mailbox",
 				     DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
 	}
-	if ((ctx->items & STATUS_MESSAGES) != 0)
+	if ((ctx->status_items & STATUS_MESSAGES) != 0)
 		doveadm_print_header_simple("messages");
-	if ((ctx->items & STATUS_RECENT) != 0)
+	if ((ctx->status_items & STATUS_RECENT) != 0)
 		doveadm_print_header_simple("recent");
-	if ((ctx->items & STATUS_UIDNEXT) != 0)
+	if ((ctx->status_items & STATUS_UIDNEXT) != 0)
 		doveadm_print_header_simple("uidnext");
-	if ((ctx->items & STATUS_UIDVALIDITY) != 0)
+	if ((ctx->status_items & STATUS_UIDVALIDITY) != 0)
 		doveadm_print_header_simple("uidvalidity");
-	if ((ctx->items & STATUS_UNSEEN) != 0)
+	if ((ctx->status_items & STATUS_UNSEEN) != 0)
 		doveadm_print_header_simple("unseen");
-	if ((ctx->items & STATUS_HIGHESTMODSEQ) != 0)
+	if ((ctx->status_items & STATUS_HIGHESTMODSEQ) != 0)
 		doveadm_print_header_simple("highestmodseq");
-	if ((ctx->items & STATUS_VIRTUAL_SIZE) != 0)
+	if ((ctx->metadata_items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0)
 		doveadm_print_header_simple("vsize");
-	if (ctx->guid)
+	if ((ctx->metadata_items & MAILBOX_METADATA_GUID) != 0)
 		doveadm_print_header_simple("guid");
 }
 
--- a/src/doveadm/doveadm-mail-search.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/doveadm/doveadm-mail-search.c	Sat Jan 01 15:52:39 2011 +0200
@@ -16,7 +16,7 @@
 	struct doveadm_mail_iter *iter;
 	struct mailbox_transaction_context *trans;
 	struct mail *mail;
-	uint8_t guid[MAIL_GUID_128_SIZE];
+	struct mailbox_metadata metadata;
 	const char *guid_str;
 	int ret = 0;
 
@@ -24,10 +24,12 @@
 		return -1;
 
 	mail = mail_alloc(trans, 0, NULL);
-	if (mailbox_get_guid(mail->box, guid) < 0)
+
+	if (mailbox_get_metadata(mail->box, MAILBOX_METADATA_GUID,
+				 &metadata) < 0)
 		ret = -1;
 	else {
-		guid_str = mail_guid_128_to_string(guid);
+		guid_str = mail_guid_128_to_string(metadata.guid);
 		while (doveadm_mail_iter_next(iter, mail)) {
 			doveadm_print(guid_str);
 			T_BEGIN {
--- a/src/doveadm/doveadm-mail.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/doveadm/doveadm-mail.c	Sat Jan 01 15:52:39 2011 +0200
@@ -71,13 +71,11 @@
 	return ctx;
 }
 
-static int mailbox_find_and_open(struct mail_user *user, const char *mailbox,
-				 struct mailbox **box_r)
+struct mailbox *
+doveadm_mailbox_find(struct mail_user *user, const char *mailbox)
 {
 	struct mail_namespace *ns;
-	struct mailbox *box;
 	string_t *str;
-	const char *orig_mailbox = mailbox;
 
 	str = t_str_new(128);
 	if (imap_utf8_to_utf7(mailbox, str) < 0)
@@ -88,10 +86,19 @@
 	if (ns == NULL)
 		i_fatal("Can't find namespace for mailbox %s", mailbox);
 
-	box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
-			    MAILBOX_FLAG_IGNORE_ACLS);
+	return mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
+			     MAILBOX_FLAG_IGNORE_ACLS);
+}
+
+static int
+doveadm_mailbox_find_and_open(struct mail_user *user, const char *mailbox,
+			      struct mailbox **box_r)
+{
+	struct mailbox *box;
+
+	box = doveadm_mailbox_find(user, mailbox);
 	if (mailbox_open(box) < 0) {
-		i_error("Opening mailbox %s failed: %s", orig_mailbox,
+		i_error("Opening mailbox %s failed: %s", mailbox,
 			mail_storage_get_last_error(mailbox_get_storage(box),
 						    NULL));
 		mailbox_free(&box);
@@ -104,12 +111,13 @@
 int doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,
 				  struct mailbox **box_r)
 {
-	if (mailbox_find_and_open(user, mailbox, box_r) < 0)
+	if (doveadm_mailbox_find_and_open(user, mailbox, box_r) < 0)
 		return -1;
 	if (mailbox_sync(*box_r, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
 		i_error("Syncing mailbox %s failed: %s", mailbox,
 			mail_storage_get_last_error(mailbox_get_storage(*box_r),
 						    NULL));
+		mailbox_free(box_r);
 		return -1;
 	}
 	return 0;
@@ -143,7 +151,7 @@
 	struct mail_storage *storage;
 	struct mailbox *box;
 
-	if (mailbox_find_and_open(user, ctx->mailbox, &box) < 0) {
+	if (doveadm_mailbox_find_and_open(user, ctx->mailbox, &box) < 0) {
 		_ctx->failed = TRUE;
 		return;
 	}
--- a/src/doveadm/doveadm-mail.h	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/doveadm/doveadm-mail.h	Sat Jan 01 15:52:39 2011 +0200
@@ -89,6 +89,8 @@
 			     const char **error_r);
 void doveadm_mail_server_flush(void);
 
+struct mailbox *
+doveadm_mailbox_find(struct mail_user *user, const char *mailbox);
 int doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,
 				  struct mailbox **box_r);
 struct mail_search_args *
--- a/src/dsync/dsync-worker-local.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/dsync/dsync-worker-local.c	Sat Jan 01 15:52:39 2011 +0200
@@ -514,12 +514,14 @@
 		MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT;
 	const enum mailbox_status_items status_items =
 		STATUS_UIDNEXT | STATUS_UIDVALIDITY |
-		STATUS_HIGHESTMODSEQ | STATUS_CACHE_FIELDS;
+		STATUS_HIGHESTMODSEQ;
+	const enum mailbox_metadata_items metadata_items =
+		MAILBOX_METADATA_CACHE_FIELDS | MAILBOX_METADATA_GUID;
 	const struct mailbox_info *info;
 	const char *storage_name;
 	struct mailbox *box;
 	struct mailbox_status status;
-	uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+	struct mailbox_metadata metadata;
 	struct local_dsync_mailbox_change *change;
 	struct local_dsync_dir_change *dir_change, change_lookup;
 	struct local_dsync_mailbox *old_lbox;
@@ -557,9 +559,8 @@
 	}
 
 	box = mailbox_alloc(info->ns->list, storage_name, flags);
-	if (mailbox_sync(box, 0) < 0 ||
-	    mailbox_get_status(box, status_items, &status) < 0 ||
-	    mailbox_get_guid(box, mailbox_guid) < 0) {
+	if (mailbox_get_status(box, status_items, &status) < 0 ||
+	    mailbox_get_metadata(box, metadata_items, &metadata) < 0) {
 		struct mail_storage *storage = mailbox_get_storage(box);
 
 		i_error("Failed to sync mailbox %s: %s", info->name,
@@ -569,13 +570,13 @@
 		return -1;
 	}
 
-	change = hash_table_lookup(worker->mailbox_changes_hash, mailbox_guid);
+	change = hash_table_lookup(worker->mailbox_changes_hash, metadata.guid);
 	if (change != NULL) {
 		/* it shouldn't be marked as deleted, but drop it to be sure */
 		change->deleted_mailbox = FALSE;
 	}
 
-	memcpy(dsync_box_r->mailbox_guid.guid, mailbox_guid,
+	memcpy(dsync_box_r->mailbox_guid.guid, metadata.guid,
 	       sizeof(dsync_box_r->mailbox_guid.guid));
 	dsync_box_r->uid_validity = status.uidvalidity;
 	dsync_box_r->uid_next = status.uidnext;
@@ -583,7 +584,7 @@
 	dsync_box_r->highest_modseq = status.highest_modseq;
 
 	p_clear(iter->ret_pool);
-	fields = array_get(status.cache_fields, &field_count);
+	fields = array_get(metadata.cache_fields, &field_count);
 	p_array_init(&dsync_box_r->cache_fields, iter->ret_pool, field_count);
 	for (i = 0; i < field_count; i++) {
 		const char *field_name = p_strdup(iter->ret_pool, fields[i]);
@@ -788,7 +789,7 @@
 	enum mailbox_flags flags = MAILBOX_FLAG_KEEP_RECENT;
 	struct local_dsync_mailbox *lbox;
 	struct mailbox *box;
-	uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+	struct mailbox_metadata metadata;
 
 	lbox = hash_table_lookup(worker->mailbox_hash, guid);
 	if (lbox == NULL) {
@@ -799,7 +800,7 @@
 
 	box = mailbox_alloc(lbox->ns->list, lbox->storage_name, flags);
 	if (mailbox_sync(box, 0) < 0 ||
-	    mailbox_get_guid(box, mailbox_guid) < 0) {
+	    mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) {
 		struct mail_storage *storage = mailbox_get_storage(box);
 
 		i_error("Failed to sync mailbox %s: %s", lbox->storage_name,
@@ -808,10 +809,10 @@
 		return -1;
 	}
 
-	if (memcmp(mailbox_guid, guid->guid, sizeof(guid->guid)) != 0) {
+	if (memcmp(metadata.guid, guid->guid, sizeof(guid->guid)) != 0) {
 		i_error("Mailbox %s changed its GUID (%s -> %s)",
 			lbox->storage_name, dsync_guid_to_str(guid),
-			mail_guid_128_to_string(mailbox_guid));
+			mail_guid_128_to_string(metadata.guid));
 		mailbox_free(&box);
 		return -1;
 	}
@@ -936,8 +937,7 @@
 	array_clear(&iter->expunges);
 	iter->expunges_set = TRUE;
 
-	if (mailbox_get_status(box, STATUS_UIDNEXT, &status) < 0)
-		i_unreached();
+	mailbox_get_open_status(box, STATUS_UIDNEXT, &status);
 	if (prev_uid + 1 >= status.uidnext) {
 		/* no expunged messages at the end of mailbox */
 		return FALSE;
--- a/src/imap/cmd-enable.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/cmd-enable.c	Sat Jan 01 15:52:39 2011 +0200
@@ -21,13 +21,13 @@
 		}
 		str = t_str_ucase(str);
 		if (strcmp(str, "CONDSTORE") == 0) {
-			client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE);
-			str_append(reply, " CONDSTORE");
-		}
-		else if (strcmp(str, "QRESYNC") == 0) {
-			client_enable(cmd->client, MAILBOX_FEATURE_QRESYNC |
-				      MAILBOX_FEATURE_CONDSTORE);
-			str_append(reply, " QRESYNC");
+			if (client_enable(cmd->client,
+					  MAILBOX_FEATURE_CONDSTORE) == 0)
+				str_append(reply, " CONDSTORE");
+		} else if (strcmp(str, "QRESYNC") == 0) {
+			if (client_enable(cmd->client, MAILBOX_FEATURE_QRESYNC |
+					  MAILBOX_FEATURE_CONDSTORE) == 0)
+				str_append(reply, " QRESYNC");
 		}
 	}
 	if (str_len(reply) > 9)
--- a/src/imap/cmd-select.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/cmd-select.c	Sat Jan 01 15:52:39 2011 +0200
@@ -276,7 +276,7 @@
 	struct client *client = ctx->cmd->client;
 	struct mailbox_status status;
 	enum mailbox_flags flags = 0;
-	int ret;
+	int ret = 0;
 
 	if (readonly)
 		flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT;
@@ -289,20 +289,17 @@
 	}
 
 	if (client->enabled_features != 0)
-		mailbox_enable(ctx->box, client->enabled_features);
-	if (mailbox_sync(ctx->box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
+		ret = mailbox_enable(ctx->box, client->enabled_features);
+	if (ret < 0 ||
+	    mailbox_sync(ctx->box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
 		client_send_storage_error(ctx->cmd,
 					  mailbox_get_storage(ctx->box));
 		return -1;
 	}
-	if (mailbox_get_status(ctx->box, STATUS_MESSAGES | STATUS_RECENT |
-			       STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
-			       STATUS_UIDNEXT | STATUS_KEYWORDS |
-			       STATUS_HIGHESTMODSEQ, &status) < 0) {
-		client_send_storage_error(ctx->cmd,
-					  mailbox_get_storage(ctx->box));
-		return -1;
-	}
+	mailbox_get_open_status(ctx->box, STATUS_MESSAGES | STATUS_RECENT |
+				STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
+				STATUS_UIDNEXT | STATUS_KEYWORDS |
+				STATUS_HIGHESTMODSEQ, &status);
 
 	client->mailbox = ctx->box;
 	client->select_counter++;
@@ -413,7 +410,7 @@
 	if (ctx->condstore) {
 		/* Enable while no mailbox is opened to avoid sending
 		   HIGHESTMODSEQ for previously opened mailbox */
-		client_enable(client, MAILBOX_FEATURE_CONDSTORE);
+		(void)client_enable(client, MAILBOX_FEATURE_CONDSTORE);
 	}
 
 	ret = select_open(ctx, storage_name, readonly);
--- a/src/imap/cmd-store.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/cmd-store.c	Sat Jan 01 15:52:39 2011 +0200
@@ -62,8 +62,8 @@
 							  "Invalid modseq");
 				return FALSE;
 			}
-			client_enable(ctx->cmd->client,
-				      MAILBOX_FEATURE_CONDSTORE);
+			(void)client_enable(ctx->cmd->client,
+					    MAILBOX_FEATURE_CONDSTORE);
 		} else {
 			client_send_command_error(ctx->cmd,
 						  "Unknown STORE modifier");
--- a/src/imap/imap-client.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/imap-client.c	Sat Jan 01 15:52:39 2011 +0200
@@ -911,28 +911,35 @@
 	return TRUE;
 }
 
-void client_enable(struct client *client, enum mailbox_feature features)
+int client_enable(struct client *client, enum mailbox_feature features)
 {
 	struct mailbox_status status;
+	int ret;
 
 	if ((client->enabled_features & features) == features)
-		return;
+		return 0;
 
 	client->enabled_features |= features;
 	if (client->mailbox == NULL)
-		return;
+		return 0;
 
-	mailbox_enable(client->mailbox, features);
-	if ((features & MAILBOX_FEATURE_CONDSTORE) != 0) {
+	ret = mailbox_enable(client->mailbox, features);
+	if ((features & MAILBOX_FEATURE_CONDSTORE) != 0 && ret == 0) {
 		/* CONDSTORE being enabled while mailbox is selected.
 		   Notify client of the latest HIGHESTMODSEQ. */
-		if (mailbox_get_status(client->mailbox,
-				       STATUS_HIGHESTMODSEQ, &status) < 0)
-			i_unreached();
-		client_send_line(client, t_strdup_printf(
-			"* OK [HIGHESTMODSEQ %llu] Highest",
-			(unsigned long long)status.highest_modseq));
+		ret = mailbox_get_status(client->mailbox,
+					 STATUS_HIGHESTMODSEQ, &status);
+		if (ret == 0) {
+			client_send_line(client, t_strdup_printf(
+				"* OK [HIGHESTMODSEQ %llu] Highest",
+				(unsigned long long)status.highest_modseq));
+		}
 	}
+	if (ret < 0) {
+		client_send_untagged_storage_error(client,
+			mailbox_get_storage(client->mailbox));
+	}
+	return ret;
 }
 
 struct imap_search_update *
--- a/src/imap/imap-client.h	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/imap-client.h	Sat Jan 01 15:52:39 2011 +0200
@@ -192,7 +192,7 @@
    have to wait for an existing SEARCH SAVE to finish. */
 bool client_handle_search_save_ambiguity(struct client_command_context *cmd);
 
-void client_enable(struct client *client, enum mailbox_feature features);
+int client_enable(struct client *client, enum mailbox_feature features);
 
 struct imap_search_update *
 client_search_update_lookup(struct client *client, const char *tag,
--- a/src/imap/imap-commands-util.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/imap-commands-util.c	Sat Jan 01 15:52:39 2011 +0200
@@ -102,8 +102,13 @@
 		mailbox_free(&box);
 		return -1;
 	}
-	if (cmd->client->enabled_features != 0)
-		mailbox_enable(box, cmd->client->enabled_features);
+	if (cmd->client->enabled_features != 0) {
+		if (mailbox_enable(box, cmd->client->enabled_features) < 0) {
+			client_send_storage_error(cmd, mailbox_get_storage(box));
+			mailbox_free(&box);
+			return -1;
+		}
+	}
 	*destbox_r = box;
 	return 0;
 }
--- a/src/imap/imap-fetch.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/imap-fetch.c	Sat Jan 01 15:52:39 2011 +0200
@@ -159,7 +159,7 @@
 	i_assert(array_count(ctx->qresync_sample_uidset) == count);
 	i_assert(count > 0);
 
-	mailbox_get_status(ctx->box, STATUS_MESSAGES, &status);
+	mailbox_get_open_status(ctx->box, STATUS_MESSAGES, &status);
 
 	/* FIXME: we could do removals from the middle as well */
 	for (i = 0; i < count && seqs[i] <= status.messages; i++) {
@@ -245,7 +245,7 @@
 					  uid_filter[i].seq2);
 	}
 
-	mailbox_get_status(ctx->box, STATUS_UIDNEXT, &status);
+	mailbox_get_open_status(ctx->box, STATUS_UIDNEXT, &status);
 	seq_range_array_remove_range(expunged_uids, status.uidnext,
 				     (uint32_t)-1);
 
@@ -751,7 +751,7 @@
 fetch_modseq_init(struct imap_fetch_context *ctx, const char *name,
 		  const struct imap_arg **args ATTR_UNUSED)
 {
-	client_enable(ctx->client, MAILBOX_FEATURE_CONDSTORE);
+	(void)client_enable(ctx->client, MAILBOX_FEATURE_CONDSTORE);
 	imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL,
 			       fetch_modseq, NULL);
 	return TRUE;
--- a/src/imap/imap-search.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/imap-search.c	Sat Jan 01 15:52:39 2011 +0200
@@ -527,7 +527,7 @@
 
 	if (ctx->have_modseqs) {
 		ctx->return_options |= SEARCH_RETURN_MODSEQ;
-		client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE);
+		(void)client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE);
 	}
 
 	ctx->box = cmd->client->mailbox;
--- a/src/imap/imap-status.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/imap-status.c	Sat Jan 01 15:52:39 2011 +0200
@@ -11,7 +11,8 @@
 			    struct imap_status_items *items_r)
 {
 	const char *item;
-	enum mailbox_status_items items;
+	enum mailbox_status_items status = 0;
+	enum mailbox_metadata_items metadata = 0;
 
 	if (IMAP_ARG_IS_EOL(args)) {
 		client_send_command_error(cmd, "Empty status list.");
@@ -19,7 +20,6 @@
 	}
 
 	memset(items_r, 0, sizeof(*items_r));
-	items = 0;
 	for (; !IMAP_ARG_IS_EOL(args); args++) {
 		if (!imap_arg_get_atom(args, &item)) {
 			/* list may contain only atoms */
@@ -30,21 +30,21 @@
 
 		item = t_str_ucase(item);
 		if (strcmp(item, "MESSAGES") == 0)
-			items |= STATUS_MESSAGES;
+			status |= STATUS_MESSAGES;
 		else if (strcmp(item, "RECENT") == 0)
-			items |= STATUS_RECENT;
+			status |= STATUS_RECENT;
 		else if (strcmp(item, "UIDNEXT") == 0)
-			items |= STATUS_UIDNEXT;
+			status |= STATUS_UIDNEXT;
 		else if (strcmp(item, "UIDVALIDITY") == 0)
-			items |= STATUS_UIDVALIDITY;
+			status |= STATUS_UIDVALIDITY;
 		else if (strcmp(item, "UNSEEN") == 0)
-			items |= STATUS_UNSEEN;
+			status |= STATUS_UNSEEN;
 		else if (strcmp(item, "HIGHESTMODSEQ") == 0)
-			items |= STATUS_HIGHESTMODSEQ;
+			status |= STATUS_HIGHESTMODSEQ;
 		else if (strcmp(item, "X-SIZE") == 0)
-			items |= STATUS_VIRTUAL_SIZE;
+			metadata |= MAILBOX_METADATA_VIRTUAL_SIZE;
 		else if (strcmp(item, "X-GUID") == 0)
-			items_r->guid = TRUE;
+			metadata |= MAILBOX_METADATA_GUID;
 		else {
 			client_send_tagline(cmd, t_strconcat(
 				"BAD Invalid status item ", item, NULL));
@@ -52,7 +52,8 @@
 		}
 	}
 
-	items_r->mailbox_items = items;
+	items_r->status = status;
+	items_r->metadata = metadata;
 	return 0;
 }
 
@@ -75,16 +76,20 @@
 		box = mailbox_alloc(ns->list, mailbox,
 				    MAILBOX_FLAG_READONLY |
 				    MAILBOX_FLAG_KEEP_RECENT);
-		if (client->enabled_features != 0)
-			mailbox_enable(box, client->enabled_features);
+		if (client->enabled_features != 0) {
+			if (mailbox_enable(box, client->enabled_features) < 0)
+				ret = -1;
+		}
 	}
 
-	if ((items->mailbox_items & STATUS_HIGHESTMODSEQ) != 0)
-		client_enable(client, MAILBOX_FEATURE_CONDSTORE);
+	if ((items->status & STATUS_HIGHESTMODSEQ) != 0)
+		(void)client_enable(client, MAILBOX_FEATURE_CONDSTORE);
 
-	ret = mailbox_get_status(box, items->mailbox_items, &result_r->status);
-	if (items->guid && ret == 0)
-		ret = mailbox_get_guid(box, result_r->mailbox_guid);
+	ret = mailbox_get_status(box, items->status, &result_r->status);
+	if (items->metadata != 0 && ret == 0) {
+		ret = mailbox_get_metadata(box, items->metadata,
+					   &result_r->metadata);
+	}
 
 	if (ret < 0) {
 		struct mail_storage *storage = mailbox_get_storage(box);
@@ -111,27 +116,27 @@
 	str_append(str, " (");
 
 	prefix_len = str_len(str);
-	if ((items->mailbox_items & STATUS_MESSAGES) != 0)
+	if ((items->status & STATUS_MESSAGES) != 0)
 		str_printfa(str, "MESSAGES %u ", status->messages);
-	if ((items->mailbox_items & STATUS_RECENT) != 0)
+	if ((items->status & STATUS_RECENT) != 0)
 		str_printfa(str, "RECENT %u ", status->recent);
-	if ((items->mailbox_items & STATUS_UIDNEXT) != 0)
+	if ((items->status & STATUS_UIDNEXT) != 0)
 		str_printfa(str, "UIDNEXT %u ", status->uidnext);
-	if ((items->mailbox_items & STATUS_UIDVALIDITY) != 0)
+	if ((items->status & STATUS_UIDVALIDITY) != 0)
 		str_printfa(str, "UIDVALIDITY %u ", status->uidvalidity);
-	if ((items->mailbox_items & STATUS_UNSEEN) != 0)
+	if ((items->status & STATUS_UNSEEN) != 0)
 		str_printfa(str, "UNSEEN %u ", status->unseen);
-	if ((items->mailbox_items & STATUS_HIGHESTMODSEQ) != 0) {
+	if ((items->status & STATUS_HIGHESTMODSEQ) != 0) {
 		str_printfa(str, "HIGHESTMODSEQ %llu ",
 			    (unsigned long long)status->highest_modseq);
 	}
-	if ((items->mailbox_items & STATUS_VIRTUAL_SIZE) != 0) {
+	if ((items->metadata & MAILBOX_METADATA_VIRTUAL_SIZE) != 0) {
 		str_printfa(str, "X-SIZE %llu ",
-			    (unsigned long long)status->virtual_size);
+			    (unsigned long long)result->metadata.virtual_size);
 	}
-	if (items->guid) {
+	if ((items->metadata & MAILBOX_METADATA_GUID) != 0) {
 		str_printfa(str, "X-GUID %s ",
-			    mail_guid_128_to_string(result->mailbox_guid));
+			    mail_guid_128_to_string(result->metadata.guid));
 	}
 
 	if (str_len(str) != prefix_len)
--- a/src/imap/imap-status.h	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/imap-status.h	Sat Jan 01 15:52:39 2011 +0200
@@ -2,14 +2,13 @@
 #define IMAP_STATUS_H
 
 struct imap_status_items {
-	enum mailbox_status_items mailbox_items;
-
-	unsigned int guid:1;
+	enum mailbox_status_items status;
+	enum mailbox_metadata_items metadata;
 };
 
 struct imap_status_result {
 	struct mailbox_status status;
-	uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+	struct mailbox_metadata metadata;
 };
 
 int imap_status_parse_items(struct client_command_context *cmd,
--- a/src/imap/imap-sync.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/imap/imap-sync.c	Sat Jan 01 15:52:39 2011 +0200
@@ -210,9 +210,6 @@
 int imap_sync_deinit(struct imap_sync_context *ctx,
 		     struct client_command_context *sync_cmd)
 {
-	const enum mailbox_status_items status_items =
-		STATUS_UIDVALIDITY | STATUS_MESSAGES | STATUS_RECENT |
-		STATUS_HIGHESTMODSEQ;
 	struct client *client = ctx->client;
 	struct mailbox_status status;
 	struct mailbox_sync_status sync_status;
@@ -223,13 +220,15 @@
 		array_free(&ctx->expunges);
 
 	if (mailbox_sync_deinit(&ctx->sync_ctx, &sync_status) < 0 ||
-	    mailbox_get_status(ctx->box, status_items, &status) < 0 ||
 	    ctx->failed) {
 		mailbox_transaction_rollback(&ctx->t);
 		array_free(&ctx->tmp_keywords);
 		i_free(ctx);
 		return -1;
 	}
+	mailbox_get_open_status(ctx->box, STATUS_UIDVALIDITY |
+				STATUS_MESSAGES | STATUS_RECENT |
+				STATUS_HIGHESTMODSEQ, &status);
 
 	ret = mailbox_transaction_commit(&ctx->t);
 
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c	Sat Jan 01 15:52:39 2011 +0200
@@ -300,9 +300,9 @@
 }
 
 static int
-mdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+mdbox_mailbox_get_guid(struct mdbox_mailbox *mbox,
+		       uint8_t guid[MAIL_GUID_128_SIZE])
 {
-	struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
 	struct mdbox_index_header hdr;
 
 	if (mdbox_read_header(mbox, &hdr) < 0)
@@ -310,7 +310,7 @@
 
 	if (mail_guid_128_is_empty(hdr.mailbox_guid)) {
 		/* regenerate it */
-		if (mdbox_write_index_header(box, NULL, NULL) < 0 ||
+		if (mdbox_write_index_header(&mbox->box, NULL, NULL) < 0 ||
 		    mdbox_read_header(mbox, &hdr) < 0)
 			return -1;
 	}
@@ -319,6 +319,20 @@
 }
 
 static int
+mdbox_mailbox_get_metadata(struct mailbox *box,
+			   enum mailbox_metadata_items items,
+			   struct mailbox_metadata *metadata_r)
+{
+	struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
+
+	if ((items & MAILBOX_METADATA_GUID) != 0) {
+		if (mdbox_mailbox_get_guid(mbox, metadata_r->guid) < 0)
+			return -1;
+	}
+	return index_mailbox_get_metadata(box, items, metadata_r);
+}
+
+static int
 mdbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
 {
 	if (!box->opened) {
@@ -403,7 +417,7 @@
 		mdbox_mailbox_delete,
 		index_storage_mailbox_rename,
 		index_storage_get_status,
-		mdbox_mailbox_get_guid,
+		mdbox_mailbox_get_metadata,
 		NULL,
 		NULL,
 		mdbox_storage_sync_init,
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c	Sat Jan 01 15:52:39 2011 +0200
@@ -303,12 +303,17 @@
 }
 
 static int
-sdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+sdbox_mailbox_get_metadata(struct mailbox *box,
+			   enum mailbox_metadata_items items,
+			   struct mailbox_metadata *metadata_r)
 {
 	struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
 
-	memcpy(guid, mbox->mailbox_guid, MAIL_GUID_128_SIZE);
-	return 0;
+	if ((items & MAILBOX_METADATA_GUID) != 0) {
+		memcpy(metadata_r->guid, mbox->mailbox_guid,
+		       MAIL_GUID_128_SIZE);
+	}
+	return index_mailbox_get_metadata(box, items, metadata_r);
 }
 
 static int
@@ -370,7 +375,7 @@
 		sdbox_mailbox_delete,
 		index_storage_mailbox_rename,
 		index_storage_get_status,
-		sdbox_mailbox_get_guid,
+		sdbox_mailbox_get_metadata,
 		NULL,
 		NULL,
 		sdbox_storage_sync_init,
--- a/src/lib-storage/index/index-search.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/index/index-search.c	Sat Jan 01 15:52:39 2011 +0200
@@ -88,7 +88,7 @@
 static void search_init_arg(struct mail_search_arg *arg,
 			    struct index_search_context *ctx)
 {
-	uint8_t guid[MAIL_GUID_128_SIZE];
+	struct mailbox_metadata metadata;
 	bool match;
 
 	switch (arg->type) {
@@ -105,12 +105,13 @@
 		ctx->have_index_args = TRUE;
 		break;
 	case SEARCH_MAILBOX_GUID:
-		if (mailbox_get_guid(ctx->box, guid) < 0) {
+		if (mailbox_get_metadata(ctx->box, MAILBOX_METADATA_GUID,
+					 &metadata) < 0) {
 			/* result will be unknown */
 			break;
 		}
 
-		match = strcmp(mail_guid_128_to_string(guid),
+		match = strcmp(mail_guid_128_to_string(metadata.guid),
 			       arg->value.str) == 0;
 		if (match != arg->not)
 			arg->match_always = TRUE;
@@ -1079,7 +1080,7 @@
 	if (gettimeofday(&ctx->last_nonblock_timeval, NULL) < 0)
 		i_fatal("gettimeofday() failed: %m");
 
-	mailbox_get_status(t->box, STATUS_MESSAGES, &status);
+	mailbox_get_open_status(t->box, STATUS_MESSAGES, &status);
 	ctx->mail_ctx.progress_max = status.messages;
 
 	i_array_init(&ctx->mail_ctx.results, 5);
--- a/src/lib-storage/index/index-status.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/index/index-status.c	Sat Jan 01 15:52:39 2011 +0200
@@ -7,9 +7,54 @@
 #include "index-storage.h"
 #include "mail-index-modseq.h"
 
+int index_storage_get_status(struct mailbox *box,
+			     enum mailbox_status_items items,
+			     struct mailbox_status *status_r)
+{
+	const struct mail_index_header *hdr;
+
+	memset(status_r, 0, sizeof(struct mailbox_status));
+
+	if (!box->opened) {
+		if (mailbox_open(box) < 0)
+			return -1;
+		if (mailbox_sync(box, 0) < 0)
+			return -1;
+	}
+
+	/* we can get most of the status items without any trouble */
+	hdr = mail_index_get_header(box->view);
+	status_r->messages = hdr->messages_count;
+	if ((items & STATUS_RECENT) != 0) {
+		status_r->recent = index_mailbox_get_recent_count(box);
+		i_assert(status_r->recent <= status_r->messages);
+	}
+	status_r->unseen = hdr->messages_count - hdr->seen_messages_count;
+	status_r->uidvalidity = hdr->uid_validity;
+	status_r->uidnext = hdr->next_uid;
+	status_r->nonpermanent_modseqs = mail_index_is_in_memory(box->index);
+	if ((items & STATUS_HIGHESTMODSEQ) != 0) {
+		status_r->highest_modseq =
+			mail_index_modseq_get_highest(box->view);
+		if (status_r->highest_modseq == 0) {
+			/* modseqs not enabled yet, but we can't return 0 */
+			status_r->highest_modseq = 1;
+		}
+	}
+
+	if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
+		mail_index_lookup_first(box->view, 0, MAIL_SEEN,
+					&status_r->first_unseen_seq);
+	}
+
+	if ((items & STATUS_KEYWORDS) != 0)
+		status_r->keywords = mail_index_get_keywords(box->index);
+	return 0;
+}
+
 static void
-index_storage_get_status_cache_fields(struct mailbox *box,
-				      struct mailbox_status *status_r)
+get_metadata_cache_fields(struct mailbox *box,
+			  struct mailbox_metadata *metadata_r)
 {
 	const struct mail_cache_field *fields;
 	enum mail_cache_decision_type dec;
@@ -26,12 +71,12 @@
 		if (dec != MAIL_CACHE_DECISION_NO)
 			array_append(cache_fields, &fields[i].name, 1);
 	}
-	status_r->cache_fields = cache_fields;
+	metadata_r->cache_fields = cache_fields;
 }
 
 static int
-index_storage_virtual_size_add_new(struct mailbox *box,
-				   struct index_vsize_header *vsize_hdr)
+virtual_size_add_new(struct mailbox *box,
+		     struct index_vsize_header *vsize_hdr)
 {
 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
 	const struct mail_index_header *hdr;
@@ -98,15 +143,17 @@
 }
 
 static int
-index_storage_get_status_virtual_size(struct mailbox *box,
-				      struct mailbox_status *status_r)
+get_metadata_virtual_size(struct mailbox *box,
+			  struct mailbox_metadata *metadata_r)
 {
 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
 	struct index_vsize_header vsize_hdr;
+	struct mailbox_status status;
 	const void *data;
 	size_t size;
 	int ret;
 
+	mailbox_get_open_status(box, STATUS_MESSAGES | STATUS_UIDNEXT, &status);
 	mail_index_get_header_ext(box->view, ibox->vsize_hdr_ext_id,
 				  &data, &size);
 	if (size == sizeof(vsize_hdr))
@@ -120,71 +167,32 @@
 		memset(&vsize_hdr, 0, sizeof(vsize_hdr));
 	}
 
-	if (vsize_hdr.highest_uid + 1 == status_r->uidnext &&
-	    vsize_hdr.message_count == status_r->messages) {
+	if (vsize_hdr.highest_uid + 1 == status.uidnext &&
+	    vsize_hdr.message_count == status.messages) {
 		/* up to date */
-		status_r->virtual_size = vsize_hdr.vsize;
+		metadata_r->virtual_size = vsize_hdr.vsize;
 		return 0;
 	}
-	if (vsize_hdr.highest_uid >= status_r->uidnext) {
+	if (vsize_hdr.highest_uid >= status.uidnext) {
 		mail_storage_set_critical(box->storage,
 			"vsize-hdr has invalid highest-uid (%u >= %u)",
-			vsize_hdr.highest_uid, status_r->uidnext);
+			vsize_hdr.highest_uid, status.uidnext);
 		memset(&vsize_hdr, 0, sizeof(vsize_hdr));
 	}
-	ret = index_storage_virtual_size_add_new(box, &vsize_hdr);
-	status_r->virtual_size = vsize_hdr.vsize;
+	ret = virtual_size_add_new(box, &vsize_hdr);
+	metadata_r->virtual_size = vsize_hdr.vsize;
 	return ret;
 }
 
-int index_storage_get_status(struct mailbox *box,
-			     enum mailbox_status_items items,
-			     struct mailbox_status *status_r)
+int index_mailbox_get_metadata(struct mailbox *box,
+			       enum mailbox_metadata_items items,
+			       struct mailbox_metadata *metadata_r)
 {
-	const struct mail_index_header *hdr;
-	int ret = 0;
-
-	memset(status_r, 0, sizeof(struct mailbox_status));
-
-	if (!box->opened) {
-		if (mailbox_open(box) < 0)
-			return -1;
-		if (mailbox_sync(box, 0) < 0)
+	if ((items & MAILBOX_METADATA_CACHE_FIELDS) != 0)
+		get_metadata_cache_fields(box, metadata_r);
+	if ((items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0) {
+		if (get_metadata_virtual_size(box, metadata_r) < 0)
 			return -1;
 	}
-
-	/* we can get most of the status items without any trouble */
-	hdr = mail_index_get_header(box->view);
-	status_r->messages = hdr->messages_count;
-	if ((items & STATUS_RECENT) != 0) {
-		status_r->recent = index_mailbox_get_recent_count(box);
-		i_assert(status_r->recent <= status_r->messages);
-	}
-	status_r->unseen = hdr->messages_count - hdr->seen_messages_count;
-	status_r->uidvalidity = hdr->uid_validity;
-	status_r->uidnext = hdr->next_uid;
-	status_r->nonpermanent_modseqs = mail_index_is_in_memory(box->index);
-	if ((items & STATUS_HIGHESTMODSEQ) != 0) {
-		status_r->highest_modseq =
-			mail_index_modseq_get_highest(box->view);
-		if (status_r->highest_modseq == 0) {
-			/* modseqs not enabled yet, but we can't return 0 */
-			status_r->highest_modseq = 1;
-		}
-	}
-
-	if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
-		mail_index_lookup_first(box->view, 0, MAIL_SEEN,
-					&status_r->first_unseen_seq);
-	}
-
-	if ((items & STATUS_KEYWORDS) != 0)
-		status_r->keywords = mail_index_get_keywords(box->index);
-	if ((items & STATUS_CACHE_FIELDS) != 0)
-		index_storage_get_status_cache_fields(box, status_r);
-	if ((items & STATUS_VIRTUAL_SIZE) != 0) {
-		if (index_storage_get_status_virtual_size(box, status_r) < 0)
-			ret = -1;
-	}
-	return ret;
+	return 0;
 }
--- a/src/lib-storage/index/index-storage.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/index/index-storage.c	Sat Jan 01 15:52:39 2011 +0200
@@ -423,7 +423,7 @@
 
 int index_storage_mailbox_delete(struct mailbox *box)
 {
-	uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+	struct mailbox_metadata metadata;
 
 	if (!box->opened) {
 		/* \noselect mailbox, try deleting only the directory */
@@ -433,7 +433,7 @@
 	if (mailbox_mark_index_deleted(box, TRUE) < 0)
 		return -1;
 
-	if (mailbox_get_guid(box, mailbox_guid) < 0)
+	if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
 		return -1;
 
 	/* Make sure the indexes are closed before trying to delete the
@@ -449,7 +449,7 @@
 	} 
 
 	mailbox_list_add_change(box->list, MAILBOX_LOG_RECORD_DELETE_MAILBOX,
-				mailbox_guid);
+				metadata.guid);
 	return index_storage_mailbox_delete_dir(box, TRUE);
 }
 
@@ -532,15 +532,17 @@
 			     struct mail *src_mail, uint32_t dest_seq)
 {
 	T_BEGIN {
-		struct mailbox_status src_status;
+		struct mailbox_metadata src_metadata;
 		const char *const *namep;
 		buffer_t *buf;
 
-		index_storage_get_status(src_mail->box, STATUS_CACHE_FIELDS,
-					 &src_status);
+		if (mailbox_get_metadata(src_mail->box,
+					 MAILBOX_METADATA_CACHE_FIELDS,
+					 &src_metadata) < 0)
+			i_unreached();
 
 		buf = buffer_create_dynamic(pool_datastack_create(), 1024);
-		array_foreach(src_status.cache_fields, namep) {
+		array_foreach(src_metadata.cache_fields, namep) {
 			mail_copy_cache_field(ctx, src_mail, dest_seq,
 					      *namep, buf);
 		}
--- a/src/lib-storage/index/index-storage.h	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/index/index-storage.h	Sat Jan 01 15:52:39 2011 +0200
@@ -108,6 +108,9 @@
 int index_storage_get_status(struct mailbox *box,
 			     enum mailbox_status_items items,
 			     struct mailbox_status *status_r);
+int index_mailbox_get_metadata(struct mailbox *box,
+			       enum mailbox_metadata_items items,
+			       struct mailbox_metadata *metadata_r);
 
 struct mail_search_context *
 index_storage_search_init(struct mailbox_transaction_context *t,
--- a/src/lib-storage/index/maildir/maildir-storage.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Sat Jan 01 15:52:39 2011 +0200
@@ -473,11 +473,18 @@
 }
 
 static int
-maildir_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+maildir_mailbox_get_metadata(struct mailbox *box,
+			     enum mailbox_metadata_items items,
+			     struct mailbox_metadata *metadata_r)
 {
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
 
-	return maildir_uidlist_get_mailbox_guid(mbox->uidlist, guid);
+	if ((items & MAILBOX_METADATA_GUID) != 0) {
+		if (maildir_uidlist_get_mailbox_guid(mbox->uidlist,
+						     metadata_r->guid) < 0)
+			return -1;
+	}
+	return index_mailbox_get_metadata(box, items, metadata_r);
 }
 
 static void maildir_mailbox_close(struct mailbox *box)
@@ -644,7 +651,7 @@
 		index_storage_mailbox_delete,
 		index_storage_mailbox_rename,
 		index_storage_get_status,
-		maildir_mailbox_get_guid,
+		maildir_mailbox_get_metadata,
 		maildir_list_index_has_changed,
 		maildir_list_index_update_sync,
 		maildir_storage_sync_init,
--- a/src/lib-storage/index/mbox/mbox-storage.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Sat Jan 01 15:52:39 2011 +0200
@@ -593,12 +593,11 @@
 }
 
 static int
-mbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+mbox_mailbox_get_guid(struct mbox_mailbox *mbox,
+		      uint8_t guid[MAIL_GUID_128_SIZE])
 {
-	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
-
-	if (mail_index_is_in_memory(box->index)) {
-		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
+	if (mail_index_is_in_memory(mbox->box.index)) {
+		mail_storage_set_error(mbox->box.storage, MAIL_ERROR_NOTPOSSIBLE,
 			"Mailbox GUIDs are not permanent without index files");
 		return -1;
 	}
@@ -610,6 +609,20 @@
 	return 0;
 }
 
+static int
+mbox_mailbox_get_metadata(struct mailbox *box,
+			  enum mailbox_metadata_items items,
+			  struct mailbox_metadata *metadata_r)
+{
+	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
+
+	if ((items & MAILBOX_METADATA_GUID) != 0) {
+		if (mbox_mailbox_get_guid(mbox, metadata_r->guid) < 0)
+			return -1;
+	}
+	return index_mailbox_get_metadata(box, items, metadata_r);
+}
+
 static void mbox_notify_changes(struct mailbox *box)
 {
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
@@ -748,7 +761,7 @@
 		index_storage_mailbox_delete,
 		index_storage_mailbox_rename,
 		index_storage_get_status,
-		mbox_mailbox_get_guid,
+		mbox_mailbox_get_metadata,
 		NULL,
 		NULL,
 		mbox_storage_sync_init,
--- a/src/lib-storage/list/index-mailbox-list-sync.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/list/index-mailbox-list-sync.c	Sat Jan 01 15:52:39 2011 +0200
@@ -340,7 +340,7 @@
 
 	view = mail_index_view_open(ilist->mail_index);
 	if (mail_index_lookup_seq(view, uid, &seq)) {
-		mailbox_get_status(box, CACHED_STATUS_ITEMS, &status);
+		mailbox_get_open_status(box, CACHED_STATUS_ITEMS, &status);
 		(void)index_list_update(ilist, box, view, seq, &status);
 	}
 	mail_index_view_close(&view);
--- a/src/lib-storage/mail-storage-private.h	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/mail-storage-private.h	Sat Jan 01 15:52:39 2011 +0200
@@ -116,7 +116,9 @@
 
 	int (*get_status)(struct mailbox *box, enum mailbox_status_items items,
 			  struct mailbox_status *status_r);
-	int (*get_guid)(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE]);
+	int (*get_metadata)(struct mailbox *box,
+			    enum mailbox_metadata_items items,
+			    struct mailbox_metadata *metadata_r);
 
 	/* Lookup sync extension record and figure out if it mailbox has
 	   changed since. Returns 1 = yes, 0 = no, -1 = error. */
--- a/src/lib-storage/mail-storage.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/mail-storage.c	Sat Jan 01 15:52:39 2011 +0200
@@ -911,21 +911,27 @@
 	return box->v.get_status(box, items, status_r);
 }
 
-int mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+void mailbox_get_open_status(struct mailbox *box,
+			     enum mailbox_status_items items,
+			     struct mailbox_status *status_r)
 {
-	if (box->v.get_guid == NULL) {
-		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
-				       "Storage doesn't support mailbox GUIDs");
-		return -1;
-	}
+	i_assert(box->opened);
+	if (box->v.get_status(box, items, status_r) < 0)
+		i_unreached();
+}
+
+int mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items,
+			 struct mailbox_metadata *metadata_r)
+{
 	if (!box->opened) {
 		if (mailbox_open(box) < 0)
 			return -1;
 	}
-	if (box->v.get_guid(box, guid) < 0)
+	if (box->v.get_metadata(box, items, metadata_r) < 0)
 		return -1;
 
-	i_assert(!mail_guid_128_is_empty(guid));
+	i_assert((items & MAILBOX_METADATA_GUID) == 0 ||
+		 !mail_guid_128_is_empty(metadata_r->guid));
 	return 0;
 }
 
--- a/src/lib-storage/mail-storage.h	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/lib-storage/mail-storage.h	Sat Jan 01 15:52:39 2011 +0200
@@ -64,9 +64,13 @@
 	STATUS_UNSEEN		= 0x10,
 	STATUS_FIRST_UNSEEN_SEQ	= 0x20,
 	STATUS_KEYWORDS		= 0x40,
-	STATUS_HIGHESTMODSEQ	= 0x80,
-	STATUS_CACHE_FIELDS	= 0x100,
-	STATUS_VIRTUAL_SIZE	= 0x200
+	STATUS_HIGHESTMODSEQ	= 0x80
+};
+
+enum mailbox_metadata_items {
+	MAILBOX_METADATA_GUID		= 0x01,
+	MAILBOX_METADATA_VIRTUAL_SIZE	= 0x02,
+	MAILBOX_METADATA_CACHE_FIELDS	= 0x04
 };
 
 enum mailbox_search_result_flags {
@@ -185,17 +189,21 @@
 
 	uint32_t first_unseen_seq;
 	uint64_t highest_modseq;
-	/* sum of virtual size of all messages in mailbox */
-	uint64_t virtual_size;
 
 	const ARRAY_TYPE(keywords) *keywords;
-	/* Fields that have "temp" or "yes" caching decision. */
-	const ARRAY_TYPE(const_string) *cache_fields;
 
 	/* Modseqs aren't permanent (index is in memory) */
 	unsigned int nonpermanent_modseqs:1;
 };
 
+struct mailbox_metadata {
+	uint8_t guid[MAIL_GUID_128_SIZE];
+	/* sum of virtual size of all messages in mailbox */
+	uint64_t virtual_size;
+	/* Fields that have "temp" or "yes" caching decision. */
+	const ARRAY_TYPE(const_string) *cache_fields;
+};
+
 struct mailbox_update {
 	/* All non-zero fields are changed. */
 	uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
@@ -393,11 +401,16 @@
    do forced CLOSE. */
 bool mailbox_is_inconsistent(struct mailbox *box);
 
-/* Gets the mailbox status information. */
+/* Gets the mailbox status information, opening the mailbox if necessary. */
 int mailbox_get_status(struct mailbox *box, enum mailbox_status_items items,
 		       struct mailbox_status *status_r);
-/* Get mailbox GUID, creating it if necessary. */
-int mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE]);
+/* Gets the mailbox status, requires that mailbox is already opened. */
+void mailbox_get_open_status(struct mailbox *box,
+			     enum mailbox_status_items items,
+			     struct mailbox_status *status_r);
+/* Gets mailbox metadata */
+int mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items,
+			 struct mailbox_metadata *metadata_r);
 /* Returns a mask of flags that are private to user in this mailbox
    (as opposed to flags shared between users). */
 enum mail_flags mailbox_get_private_flags_mask(struct mailbox *box);
--- a/src/plugins/fts-solr/fts-backend-solr.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/plugins/fts-solr/fts-backend-solr.c	Sat Jan 01 15:52:39 2011 +0200
@@ -298,7 +298,7 @@
 
 	box_name = fts_box_get_root(box, &ns);
 
-	mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
+	mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status);
 	str_printfa(str, "uidv:%u+box:", status.uidvalidity);
 	solr_quote_http(str, box_name);
 	solr_add_ns_query_http(str, backend, ns);
@@ -340,7 +340,7 @@
 
 	box_name = fts_box_get_root(box, &ns);
 
-	mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
+	mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status);
 	str_printfa(str, "uidv:%u+box:", status.uidvalidity);
 	solr_quote_http(str, box_name);
 	solr_add_ns_query_http(str, backend, ns);
@@ -539,7 +539,7 @@
 	ctx->ctx.backend = backend;
 	ctx->cmd = str_new(default_pool, SOLR_CMDBUF_SIZE);
 
-	mailbox_get_status(backend->box, STATUS_UIDVALIDITY, &status);
+	mailbox_get_open_status(backend->box, STATUS_UIDVALIDITY, &status);
 	ctx->uid_validity = status.uidvalidity;
 
 	*ctx_r = &ctx->ctx;
@@ -737,7 +737,7 @@
 {
 	struct mailbox_status status;
 
-	mailbox_get_status(mail->box, STATUS_UIDVALIDITY, &status);
+	mailbox_get_open_status(mail->box, STATUS_UIDVALIDITY, &status);
 
 	T_BEGIN {
 		string_t *cmd;
@@ -807,7 +807,7 @@
 	bool virtual;
 
 	virtual = strcmp(box->storage->name, "virtual") == 0;
-	mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
+	mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status);
 
 	str = t_str_new(256);
 	if (!virtual) {
--- a/src/plugins/fts-squat/fts-backend-squat.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/plugins/fts-squat/fts-backend-squat.c	Sat Jan 01 15:52:39 2011 +0200
@@ -69,7 +69,7 @@
 		return NULL;
 	}
 
-	mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
+	mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status);
 	if (storage->set->mmap_disable)
 		flags |= SQUAT_INDEX_FLAG_MMAP_DISABLE;
 	if (storage->set->mail_nfs_index)
--- a/src/plugins/fts/fts-storage.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/plugins/fts/fts-storage.c	Sat Jan 01 15:52:39 2011 +0200
@@ -396,8 +396,8 @@
 		ret = strcmp(vname, last_uids[uidi].mailbox);
 		if (ret == 0) {
 			/* match. check also that uidvalidity matches. */
-			mailbox_get_status(boxes[boxi].box, STATUS_UIDVALIDITY,
-					   &status);
+			mailbox_get_open_status(boxes[boxi].box,
+						STATUS_UIDVALIDITY, &status);
 			if (status.uidvalidity != last_uids[uidi].uidvalidity) {
 				uidi++;
 				continue;
@@ -501,8 +501,8 @@
 	struct mailbox_status status;
 	int ret;
 
-	mailbox_get_status(fctx->t->box, STATUS_MESSAGES | STATUS_UIDNEXT,
-			   &status);
+	mailbox_get_open_status(fctx->t->box, STATUS_MESSAGES | STATUS_UIDNEXT,
+				&status);
 	if (status.messages == fctx->fbox->last_messages_count &&
 	    status.uidnext == fctx->fbox->last_uidnext) {
 		/* no new messages since last check */
@@ -540,8 +540,8 @@
 		ret = -1;
 
 	if (ret == 0) {
-		mailbox_get_status(box, STATUS_MESSAGES | STATUS_UIDNEXT,
-				   &status);
+		mailbox_get_open_status(box, STATUS_MESSAGES | STATUS_UIDNEXT,
+					&status);
 		fbox->last_messages_count = status.messages;
 		fbox->last_uidnext = status.uidnext;
 	}
@@ -778,7 +778,8 @@
 	struct fts_mailbox *fbox = FTS_CONTEXT(ctx->transaction->box);
 	struct mailbox_status status;
 
-	mailbox_get_status(ctx->transaction->box, STATUS_MESSAGES, &status);
+	mailbox_get_open_status(ctx->transaction->box,
+				STATUS_MESSAGES, &status);
 
 	fctx->seqs_set = FALSE;
 	ctx->seq = fctx->first_nonindexed_seq - 1;
--- a/src/plugins/virtual/virtual-save.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/plugins/virtual/virtual-save.c	Sat Jan 01 15:52:39 2011 +0200
@@ -50,7 +50,7 @@
 		return NULL;
 
 	t_array_init(&kw_strings, src_keywords->count + 1);
-	mailbox_get_status(src_box, STATUS_KEYWORDS, &status);
+	mailbox_get_open_status(src_box, STATUS_KEYWORDS, &status);
 
 	for (i = 0; i < src_keywords->count; i++) {
 		kwp = array_idx(status.keywords, src_keywords->idx[i]);
--- a/src/plugins/virtual/virtual-storage.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/plugins/virtual/virtual-storage.c	Sat Jan 01 15:52:39 2011 +0200
@@ -335,12 +335,16 @@
 }
 
 static int
-virtual_mailbox_get_guid(struct mailbox *box,
-			 uint8_t guid[MAIL_GUID_128_SIZE] ATTR_UNUSED)
+virtual_mailbox_get_metadata(struct mailbox *box,
+			     enum mailbox_metadata_items items,
+			     struct mailbox_metadata *metadata_r)
 {
-	mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
-			       "Virtual mailboxes have no GUIDs");
-	return -1;
+	if ((items & MAILBOX_METADATA_GUID) != 0) {
+		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
+				       "Virtual mailboxes have no GUIDs");
+		return -1;
+	}
+	return index_mailbox_get_metadata(box, items, metadata_r);
 }
 
 static void
@@ -437,7 +441,7 @@
 	if (bbox == NULL)
 		return FALSE;
 
-	mailbox_get_status(bbox->box, STATUS_UIDVALIDITY, &status);
+	mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY, &status);
 	if (status.uidvalidity != backend_uidvalidity)
 		return FALSE;
 
@@ -517,7 +521,7 @@
 		index_storage_mailbox_delete,
 		index_storage_mailbox_rename,
 		index_storage_get_status,
-		virtual_mailbox_get_guid,
+		virtual_mailbox_get_metadata,
 		NULL,
 		NULL,
 		virtual_storage_sync_init,
--- a/src/plugins/virtual/virtual-sync.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/plugins/virtual/virtual-sync.c	Sat Jan 01 15:52:39 2011 +0200
@@ -986,8 +986,8 @@
 	unsigned int mailbox_offset;
 	uint64_t wanted_ondisk_highest_modseq;
 
-	mailbox_get_status(bbox->box, STATUS_UIDVALIDITY |
-			   STATUS_HIGHESTMODSEQ, &status);
+	mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY |
+				STATUS_HIGHESTMODSEQ, &status);
 	wanted_ondisk_highest_modseq =
 		array_count(&bbox->sync_pending_removes) > 0 ? 0 :
 		status.highest_modseq;
@@ -1053,7 +1053,7 @@
 		if (mailbox_sync(bbox->box, sync_flags) < 0)
 			return -1;
 
-		mailbox_get_status(bbox->box, STATUS_UIDVALIDITY, &status);
+		mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY, &status);
 		virtual_backend_box_sync_mail_set(bbox);
 		if (status.uidvalidity != bbox->sync_uid_validity) {
 			/* UID validity changed since last sync (or this is
--- a/src/pop3/pop3-client.c	Wed Dec 29 11:43:01 2010 +0200
+++ b/src/pop3/pop3-client.c	Sat Jan 01 15:52:39 2011 +0200
@@ -116,7 +116,7 @@
 
 	*failed_uid_r = 0;
 
-	mailbox_get_status(client->mailbox, STATUS_UIDVALIDITY, &status);
+	mailbox_get_open_status(client->mailbox, STATUS_UIDVALIDITY, &status);
 	client->uid_validity = status.uidvalidity;
 	client->messages_count = status.messages;