diff -r ddfe3a0f75e6 src/doveadm/doveadm-dump-index.c
--- a/src/doveadm/doveadm-dump-index.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/doveadm/doveadm-dump-index.c	Thu Dec 08 09:32:03 2011 +0200
@@ -9,7 +9,6 @@
 #include "message-part-serialize.h"
 #include "mail-index-private.h"
 #include "mail-cache-private.h"
-#include "mail-cache-private.h"
 #include "mail-index-modseq.h"
 #include "doveadm-dump.h"
 
@@ -344,7 +343,7 @@
 			printf("   - ");
 		printf("%-4s %.16s\n",
 		       cache_decision2str(field->decision),
-		       unixdate2str(cache->fields[cache_idx].last_used));
+		       unixdate2str(field->last_used));
 	}
 }
 
diff -r ddfe3a0f75e6 src/dsync/dsync-data.c
--- a/src/dsync/dsync-data.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/dsync-data.c	Thu Dec 08 09:32:03 2011 +0200
@@ -10,7 +10,8 @@
 dsync_mailbox_dup(pool_t pool, const struct dsync_mailbox *box)
 {
 	struct dsync_mailbox *dest;
-	const char *const *cache_fields = NULL, *dup;
+	const struct mailbox_cache_field *cache_fields = NULL;
+	struct mailbox_cache_field *dup;
 	unsigned int i, count = 0;
 
 	dest = p_new(pool, struct dsync_mailbox, 1);
@@ -24,8 +25,9 @@
 	else {
 		p_array_init(&dest->cache_fields, pool, count);
 		for (i = 0; i < count; i++) {
-			dup = p_strdup(pool, cache_fields[i]);
-			array_append(&dest->cache_fields, &dup, 1);
+			dup = array_append_space(&dest->cache_fields);
+			*dup = cache_fields[i];
+			dup->name = p_strdup(pool, dup->name);
 		}
 	}
 	return dest;
diff -r ddfe3a0f75e6 src/dsync/dsync-data.h
--- a/src/dsync/dsync-data.h	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/dsync-data.h	Thu Dec 08 09:32:03 2011 +0200
@@ -28,7 +28,7 @@
 	   otherwise it's the last rename timestamp. */
 	time_t last_change;
 	enum dsync_mailbox_flags flags;
-	ARRAY_TYPE(const_string) cache_fields;
+	ARRAY_TYPE(mailbox_cache_field) cache_fields;
 };
 ARRAY_DEFINE_TYPE(dsync_mailbox, struct dsync_mailbox *);
 #define dsync_mailbox_is_noselect(dsync_box) \
diff -r ddfe3a0f75e6 src/dsync/dsync-proxy-client.c
--- a/src/dsync/dsync-proxy-client.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/dsync-proxy-client.c	Thu Dec 08 09:32:03 2011 +0200
@@ -893,7 +893,7 @@
 static void
 proxy_client_worker_select_mailbox(struct dsync_worker *_worker,
 				   const mailbox_guid_t *mailbox,
-				   const ARRAY_TYPE(const_string) *cache_fields)
+				   const ARRAY_TYPE(mailbox_cache_field) *cache_fields)
 {
 	struct proxy_client_dsync_worker *worker =
 		(struct proxy_client_dsync_worker *)_worker;
@@ -908,7 +908,7 @@
 		str_append(str, "BOX-SELECT\t");
 		dsync_proxy_mailbox_guid_export(str, mailbox);
 		if (cache_fields != NULL)
-			dsync_proxy_strings_export(str, cache_fields);
+			dsync_proxy_cache_fields_export(str, cache_fields);
 		str_append_c(str, '\n');
 		proxy_client_worker_cmd(worker, str);
 	} T_END;
diff -r ddfe3a0f75e6 src/dsync/dsync-proxy-server-cmd.c
--- a/src/dsync/dsync-proxy-server-cmd.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/dsync-proxy-server-cmd.c	Thu Dec 08 09:32:03 2011 +0200
@@ -315,7 +315,7 @@
 cmd_box_select(struct dsync_proxy_server *server, const char *const *args)
 {
 	struct dsync_mailbox box;
-	unsigned int i, count;
+	const char *error;
 
 	memset(&box, 0, sizeof(box));
 	if (args[0] == NULL ||
@@ -325,10 +325,11 @@
 	}
 	args++;
 
-	count = str_array_length(args);
-	t_array_init(&box.cache_fields, count + 1);
-	for (i = 0; i < count; i++)
-		array_append(&box.cache_fields, &args[i], 1);
+	if (dsync_proxy_cache_fields_import(args, pool_datastack_create(),
+					    &box.cache_fields, &error) < 0) {
+		i_error("box-select: %s", error);
+		return -1;
+	}
 	dsync_worker_select_mailbox(server->worker, &box);
 	return 1;
 }
diff -r ddfe3a0f75e6 src/dsync/dsync-proxy.c
--- a/src/dsync/dsync-proxy.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/dsync-proxy.c	Thu Dec 08 09:32:03 2011 +0200
@@ -8,27 +8,104 @@
 #include "hex-binary.h"
 #include "mail-types.h"
 #include "imap-util.h"
+#include "mail-cache.h"
 #include "dsync-data.h"
 #include "dsync-proxy.h"
 
 #include <stdlib.h>
 
-void dsync_proxy_strings_export(string_t *str,
-				const ARRAY_TYPE(const_string) *strings)
+#define DSYNC_CACHE_DECISION_NO 'n'
+#define DSYNC_CACHE_DECISION_YES 'y'
+#define DSYNC_CACHE_DECISION_TEMP 't'
+#define DSYNC_CACHE_DECISION_FORCED 'f'
+
+void dsync_proxy_cache_fields_export(string_t *str,
+				     const ARRAY_TYPE(mailbox_cache_field) *_fields)
 {
-	const char *const *fields;
+	const struct mailbox_cache_field *fields;
 	unsigned int i, count;
 
-	if (!array_is_created(strings))
+	if (!array_is_created(_fields))
 		return;
 
-	fields = array_get(strings, &count);
+	fields = array_get(_fields, &count);
 	for (i = 0; i < count; i++) {
 		str_append_c(str, '\t');
-		str_tabescape_write(str, fields[i]);
+		str_tabescape_write(str, fields[i].name);
+		str_append_c(str, '\t');
+		switch (fields[i].decision & ~MAIL_CACHE_DECISION_FORCED) {
+		case MAIL_CACHE_DECISION_NO:
+			str_append_c(str, DSYNC_CACHE_DECISION_NO);
+			break;
+		case MAIL_CACHE_DECISION_YES:
+			str_append_c(str, DSYNC_CACHE_DECISION_YES);
+			break;
+		case MAIL_CACHE_DECISION_TEMP:
+			str_append_c(str, DSYNC_CACHE_DECISION_TEMP);
+			break;
+		}
+		if ((fields[i].decision & MAIL_CACHE_DECISION_FORCED) != 0)
+			str_append_c(str, DSYNC_CACHE_DECISION_FORCED);
+		str_printfa(str, "\t%ld", fields[i].last_used);
 	}
 }
 
+static int dsync_proxy_cache_dec_parse(const char *str,
+				       enum mail_cache_decision_type *dec_r)
+{
+	switch (*str++) {
+	case DSYNC_CACHE_DECISION_NO:
+		*dec_r = MAIL_CACHE_DECISION_NO;
+		break;
+	case DSYNC_CACHE_DECISION_YES:
+		*dec_r = MAIL_CACHE_DECISION_YES;
+		break;
+	case DSYNC_CACHE_DECISION_TEMP:
+		*dec_r = MAIL_CACHE_DECISION_TEMP;
+		break;
+	default:
+		return -1;
+	}
+	if (*str == DSYNC_CACHE_DECISION_FORCED) {
+		*dec_r |= MAIL_CACHE_DECISION_FORCED;
+		str++;
+	}
+	if (*str != '\0')
+		return -1;
+	return 0;
+}
+
+int dsync_proxy_cache_fields_import(const char *const *args, pool_t pool,
+				    ARRAY_TYPE(mailbox_cache_field) *fields,
+				    const char **error_r)
+{
+	struct mailbox_cache_field *cache_field;
+	enum mail_cache_decision_type dec;
+	unsigned int i, count = str_array_length(args);
+
+	if (count % 3 != 0) {
+		*error_r = "Invalid mailbox cache fields";
+		return -1;
+	}
+	if (!array_is_created(fields))
+		p_array_init(fields, pool, (count/3) + 1);
+	for (i = 0; i < count; i += 3) {
+		cache_field = array_append_space(fields);
+		cache_field->name = p_strdup(pool, args[i]);
+
+		if (dsync_proxy_cache_dec_parse(args[i+1], &dec) < 0) {
+			*error_r = "Invalid cache decision";
+			return -1;
+		}
+		cache_field->decision = dec;
+		if (str_to_time(args[i+2], &cache_field->last_used) < 0) {
+			*error_r = "Invalid cache last_used";
+			return -1;
+		}
+	}
+	return 0;
+}
+
 void dsync_proxy_msg_export(string_t *str,
 			    const struct dsync_message *msg)
 {
@@ -178,7 +255,7 @@
 		    box->uid_validity, box->uid_next, box->message_count,
 		    (unsigned long long)box->highest_modseq,
 		    box->first_recent_uid);
-	dsync_proxy_strings_export(str, &box->cache_fields);
+	dsync_proxy_cache_fields_export(str, &box->cache_fields);
 }
 
 int dsync_proxy_mailbox_import_unescaped(pool_t pool, const char *const *args,
@@ -270,11 +347,9 @@
 
 	args += i;
 	count -= i;
-	p_array_init(&box_r->cache_fields, pool, count + 1);
-	for (i = 0; i < count; i++) {
-		const char *field_name = p_strdup(pool, args[i]);
-		array_append(&box_r->cache_fields, &field_name, 1);
-	}
+	if (dsync_proxy_cache_fields_import(args, pool, &box_r->cache_fields,
+					    error_r) < 0)
+		return -1;
 	return 0;
 }
 
diff -r ddfe3a0f75e6 src/dsync/dsync-proxy.h
--- a/src/dsync/dsync-proxy.h	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/dsync-proxy.h	Thu Dec 08 09:32:03 2011 +0200
@@ -6,14 +6,17 @@
 #define DSYNC_PROXY_CLIENT_TIMEOUT_MSECS (14*60*1000)
 #define DSYNC_PROXY_SERVER_TIMEOUT_MSECS (15*60*1000)
 
-#define DSYNC_PROXY_CLIENT_GREETING_LINE "dsync-client\t1"
-#define DSYNC_PROXY_SERVER_GREETING_LINE "dsync-server\t1"
+#define DSYNC_PROXY_CLIENT_GREETING_LINE "dsync-client\t2"
+#define DSYNC_PROXY_SERVER_GREETING_LINE "dsync-server\t2"
 
 struct dsync_message;
 struct dsync_mailbox;
 
-void dsync_proxy_strings_export(string_t *str,
-				const ARRAY_TYPE(const_string) *strings);
+void dsync_proxy_cache_fields_export(string_t *str,
+				     const ARRAY_TYPE(mailbox_cache_field) *fields);
+int dsync_proxy_cache_fields_import(const char *const *args, pool_t pool,
+				    ARRAY_TYPE(mailbox_cache_field) *fields,
+				    const char **error_r);
 
 void dsync_proxy_msg_export(string_t *str, const struct dsync_message *msg);
 int dsync_proxy_msg_parse_flags(pool_t pool, const char *str,
diff -r ddfe3a0f75e6 src/dsync/dsync-worker-local.c
--- a/src/dsync/dsync-worker-local.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/dsync-worker-local.c	Thu Dec 08 09:32:03 2011 +0200
@@ -528,8 +528,8 @@
 	struct local_dsync_dir_change *dir_change, change_lookup;
 	struct local_dsync_mailbox *old_lbox;
 	enum mail_error error;
-	const char *const *fields;
-	unsigned int i, field_count;
+	struct mailbox_cache_field *cache_fields;
+	unsigned int i, cache_field_count;
 
 	memset(dsync_box_r, 0, sizeof(*dsync_box_r));
 
@@ -595,12 +595,14 @@
 	dsync_box_r->highest_modseq = status.highest_modseq;
 
 	p_clear(iter->ret_pool);
-	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]);
-
-		array_append(&dsync_box_r->cache_fields, &field_name, 1);
+	p_array_init(&dsync_box_r->cache_fields, iter->ret_pool,
+		     array_count(metadata.cache_fields));
+	array_append_array(&dsync_box_r->cache_fields, metadata.cache_fields);
+	cache_fields = array_get_modifiable(&dsync_box_r->cache_fields,
+					    &cache_field_count);
+	for (i = 0; i < cache_field_count; i++) {
+		cache_fields[i].name =
+			p_strdup(iter->ret_pool, cache_fields[i].name);
 	}
 
 	old_lbox = hash_table_lookup(worker->mailbox_hash,
@@ -1443,25 +1445,26 @@
 
 static void
 local_worker_set_cache_fields(struct local_dsync_worker *worker,
-			      const ARRAY_TYPE(const_string) *cache_fields)
+			      const ARRAY_TYPE(mailbox_cache_field) *cache_fields)
 {
 	struct mailbox_update update;
-	const char *const *fields, **new_fields;
+	const struct mailbox_cache_field *fields;
+	struct mailbox_cache_field *new_fields;
 	unsigned int count;
 
 	fields = array_get(cache_fields, &count);
-	new_fields = t_new(const char *, count + 1);
-	memcpy(new_fields, fields, sizeof(const char *) * count);
+	new_fields = t_new(struct mailbox_cache_field, count + 1);
+	memcpy(new_fields, fields, sizeof(struct mailbox_cache_field) * count);
 
 	memset(&update, 0, sizeof(update));
-	update.cache_fields = new_fields;
+	update.cache_updates = new_fields;
 	mailbox_update(worker->selected_box, &update);
 }
 
 static void
 local_worker_select_mailbox(struct dsync_worker *_worker,
 			    const mailbox_guid_t *mailbox,
-			    const ARRAY_TYPE(const_string) *cache_fields)
+			    const ARRAY_TYPE(mailbox_cache_field) *cache_fields)
 {
 	struct local_dsync_worker *worker =
 		(struct local_dsync_worker *)_worker;
diff -r ddfe3a0f75e6 src/dsync/dsync-worker-private.h
--- a/src/dsync/dsync-worker-private.h	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/dsync-worker-private.h	Thu Dec 08 09:32:03 2011 +0200
@@ -50,7 +50,7 @@
 
 	void (*select_mailbox)(struct dsync_worker *worker,
 			       const mailbox_guid_t *mailbox,
-			       const ARRAY_TYPE(const_string) *cache_fields);
+			       const ARRAY_TYPE(mailbox_cache_field) *cache_fields);
 	void (*msg_update_metadata)(struct dsync_worker *worker,
 				    const struct dsync_message *msg);
 	void (*msg_update_uid)(struct dsync_worker *worker,
diff -r ddfe3a0f75e6 src/dsync/test-dsync-common.c
--- a/src/dsync/test-dsync-common.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/test-dsync-common.c	Thu Dec 08 09:32:03 2011 +0200
@@ -44,7 +44,7 @@
 bool dsync_mailboxes_equal(const struct dsync_mailbox *box1,
 			   const struct dsync_mailbox *box2)
 {
-	const char *const *f1 = NULL, *const *f2 = NULL;
+	const struct mailbox_cache_field *f1 = NULL, *f2 = NULL;
 	unsigned int i, f1_count = 0, f2_count = 0;
 
 	if (strcmp(box1->name, box2->name) != 0 ||
@@ -63,7 +63,9 @@
 	if (f1_count != f2_count)
 		return FALSE;
 	for (i = 0; i < f1_count; i++) {
-		if (strcmp(f1[i], f2[i]) != 0)
+		if (strcmp(f1[i].name, f2[i].name) != 0 ||
+		    f1[i].decision != f2[i].decision ||
+		    f1[i].last_used != f2[i].last_used)
 			return FALSE;
 	}
 	return TRUE;
diff -r ddfe3a0f75e6 src/dsync/test-dsync-proxy.c
--- a/src/dsync/test-dsync-proxy.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/test-dsync-proxy.c	Thu Dec 08 09:32:03 2011 +0200
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "array.h"
 #include "str.h"
+#include "mail-cache.h"
 #include "dsync-proxy.h"
 #include "test-dsync-common.h"
 #include "test-common.h"
@@ -85,8 +86,10 @@
 
 static void test_dsync_proxy_mailbox(void)
 {
-	static const char *cache1 = "cache1";
-	static const char *cache2 = "cache2";
+	static struct mailbox_cache_field cache1 =
+		{ "cache1", MAIL_CACHE_DECISION_NO, 1234 };
+	static struct mailbox_cache_field cache2 =
+		{ "cache2", MAIL_CACHE_DECISION_TEMP | MAIL_CACHE_DECISION_FORCED, 0 };
 	string_t *str;
 	struct dsync_mailbox box_in, box_out;
 	const char *error;
diff -r ddfe3a0f75e6 src/dsync/test-dsync-worker.c
--- a/src/dsync/test-dsync-worker.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/test-dsync-worker.c	Thu Dec 08 09:32:03 2011 +0200
@@ -285,7 +285,7 @@
 static void
 test_worker_select_mailbox(struct dsync_worker *_worker,
 			   const mailbox_guid_t *mailbox,
-			   const ARRAY_TYPE(const_string) *cache_fields)
+			   const ARRAY_TYPE(mailbox_cache_field) *cache_fields)
 {
 	struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker;
 	struct dsync_mailbox box;
diff -r ddfe3a0f75e6 src/dsync/test-dsync-worker.h
--- a/src/dsync/test-dsync-worker.h	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/dsync/test-dsync-worker.h	Thu Dec 08 09:32:03 2011 +0200
@@ -83,7 +83,7 @@
 	mailbox_guid_t selected_mailbox;
 	mailbox_guid_t *msg_iter_mailboxes;
 	unsigned int msg_iter_mailbox_count;
-	const ARRAY_TYPE(const_string) *cache_fields;
+	const ARRAY_TYPE(mailbox_cache_field) *cache_fields;
 };
 
 struct dsync_worker *dsync_worker_init_test(void);
diff -r ddfe3a0f75e6 src/lib-index/mail-cache-compress.c
--- a/src/lib-index/mail-cache-compress.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-index/mail-cache-compress.c	Thu Dec 08 09:32:03 2011 +0200
@@ -208,7 +208,7 @@
 			/* if the decision isn't forced and this field hasn't
 			   been accessed for a while, drop it */
 			if ((dec & MAIL_CACHE_DECISION_FORCED) == 0 &&
-			    (time_t)priv->last_used < max_drop_time &&
+			    priv->field.last_used < max_drop_time &&
 			    !priv->adding) {
 				dec = MAIL_CACHE_DECISION_NO;
 				priv->field.decision = dec;
@@ -218,7 +218,7 @@
 			if ((dec & ~MAIL_CACHE_DECISION_FORCED) ==
 			    MAIL_CACHE_DECISION_NO && !priv->adding) {
 				priv->used = FALSE;
-				priv->last_used = 0;
+				priv->field.last_used = 0;
 			}
 
 			ctx.field_file_map[i] = !priv->used ?
diff -r ddfe3a0f75e6 src/lib-index/mail-cache-decisions.c
--- a/src/lib-index/mail-cache-decisions.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-index/mail-cache-decisions.c	Thu Dec 08 09:32:03 2011 +0200
@@ -85,9 +85,9 @@
 	mail_index_lookup_uid(view->view, seq, &uid);
 	hdr = mail_index_get_header(view->view);
 
-	if (ioloop_time - cache->fields[field].last_used > 3600*24) {
+	if (ioloop_time - cache->fields[field].field.last_used > 3600*24) {
 		/* update last_used about once a day */
-		cache->fields[field].last_used = (uint32_t)ioloop_time;
+		cache->fields[field].field.last_used = (uint32_t)ioloop_time;
 		if (cache->field_file_map[field] != (uint32_t)-1)
 			cache->field_header_write_pending = TRUE;
 	}
diff -r ddfe3a0f75e6 src/lib-index/mail-cache-fields.c
--- a/src/lib-index/mail-cache-fields.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-index/mail-cache-fields.c	Thu Dec 08 09:32:03 2011 +0200
@@ -65,11 +65,35 @@
 	return 0;
 }
 
+static void
+mail_cache_field_update(struct mail_cache *cache,
+			const struct mail_cache_field *newfield)
+{
+	struct mail_cache_field_private *orig;
+
+	i_assert(newfield->type < MAIL_CACHE_FIELD_COUNT);
+
+	orig = &cache->fields[newfield->idx];
+	if (newfield->decision != MAIL_CACHE_DECISION_NO &&
+	    orig->field.decision != newfield->decision) {
+		orig->field.decision = newfield->decision;
+		orig->decision_dirty = TRUE;
+	}
+	if (orig->field.last_used < newfield->last_used) {
+		orig->field.last_used = newfield->last_used;
+		orig->decision_dirty = TRUE;
+	}
+	if (orig->decision_dirty)
+		cache->field_header_write_pending = TRUE;
+
+	(void)field_type_verify(cache, newfield->idx,
+				newfield->type, newfield->field_size);
+}
+
 void mail_cache_register_fields(struct mail_cache *cache,
 				struct mail_cache_field *fields,
 				unsigned int fields_count)
 {
-	struct mail_cache_field *orig_field;
 	void *orig_key, *orig_value;
 	char *name;
 	unsigned int new_idx;
@@ -80,18 +104,9 @@
 		if (hash_table_lookup_full(cache->field_name_hash,
 					   fields[i].name,
 					   &orig_key, &orig_value)) {
-			i_assert(fields[i].type < MAIL_CACHE_FIELD_COUNT);
-
 			fields[i].idx =
 				POINTER_CAST_TO(orig_value, unsigned int);
-
-			orig_field = &cache->fields[fields[i].idx].field;
-			if (orig_field->decision == MAIL_CACHE_DECISION_NO)
-				orig_field->decision = fields[i].decision;
-
-			(void)field_type_verify(cache, fields[i].idx,
-						fields[i].type,
-						fields[i].field_size);
+			mail_cache_field_update(cache, &fields[i]);
 			continue;
 		}
 
@@ -130,6 +145,7 @@
 		name = p_strdup(cache->field_pool, fields[i].name);
 		cache->fields[idx].field = fields[i];
 		cache->fields[idx].field.name = name;
+		cache->fields[idx].field.last_used = fields[i].last_used;
 		cache->field_file_map[idx] = (uint32_t)-1;
 
 		if (!field_has_fixed_size(cache->fields[idx].field.type))
@@ -387,12 +403,12 @@
 		cache->file_field_map[i] = fidx;
 
 		/* update last_used if it's newer than ours */
-		if (last_used[i] > cache->fields[fidx].last_used)
-			cache->fields[fidx].last_used = last_used[i];
+		if (last_used[i] > cache->fields[fidx].field.last_used)
+			cache->fields[fidx].field.last_used = last_used[i];
 
 		dec = cache->fields[fidx].field.decision;
-		if ((time_t)cache->fields[fidx].last_used < max_drop_time &&
-		    cache->fields[fidx].last_used != 0 &&
+		if (cache->fields[fidx].field.last_used < max_drop_time &&
+		    cache->fields[fidx].field.last_used != 0 &&
 		    (dec & MAIL_CACHE_DECISION_FORCED) == 0 &&
 		    dec != MAIL_CACHE_DECISION_NO) {
 			/* time to drop this field. don't bother dropping
@@ -469,7 +485,7 @@
 	buffer = buffer_create_dynamic(pool_datastack_create(), 256);
 
 	copy_to_buf(cache, buffer, FALSE,
-		    offsetof(struct mail_cache_field_private, last_used),
+		    offsetof(struct mail_cache_field, last_used),
 		    sizeof(uint32_t));
 	ret = mail_cache_write(cache, buffer->data, buffer->used,
 			       offset + MAIL_CACHE_FIELD_LAST_USED());
@@ -532,7 +548,7 @@
 
 	/* we have to keep the field order for the existing fields. */
 	copy_to_buf(cache, dest, TRUE,
-		    offsetof(struct mail_cache_field_private, last_used),
+		    offsetof(struct mail_cache_field, last_used),
 		    sizeof(uint32_t));
 	copy_to_buf(cache, dest, TRUE,
 		    offsetof(struct mail_cache_field, field_size),
diff -r ddfe3a0f75e6 src/lib-index/mail-cache-private.h
--- a/src/lib-index/mail-cache-private.h	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-index/mail-cache-private.h	Thu Dec 08 09:32:03 2011 +0200
@@ -117,7 +117,6 @@
 	struct mail_cache_field field;
 
 	uint32_t uid_highwater;
-	uint32_t last_used;
 
 	/* Unused fields aren't written to cache file */
 	unsigned int used:1;
diff -r ddfe3a0f75e6 src/lib-index/mail-cache.h
--- a/src/lib-index/mail-cache.h	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-index/mail-cache.h	Thu Dec 08 09:32:03 2011 +0200
@@ -38,6 +38,8 @@
 	enum mail_cache_field_type type;
 	unsigned int field_size;
 	enum mail_cache_decision_type decision;
+	/* If higher than the current last_used field, update it */
+	time_t last_used;
 };
 
 struct mail_cache *mail_cache_open_or_create(struct mail_index *index);
diff -r ddfe3a0f75e6 src/lib-storage/index/dbox-multi/mdbox-storage.c
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c	Thu Dec 08 09:32:03 2011 +0200
@@ -401,8 +401,8 @@
 		if (mailbox_open(box) < 0)
 			return -1;
 	}
-	if (update->cache_fields != NULL)
-		index_storage_mailbox_update_cache_fields(box, update);
+	if (update->cache_updates != NULL)
+		index_storage_mailbox_update_cache(box, update);
 	return mdbox_write_index_header(box, update, NULL);
 }
 
diff -r ddfe3a0f75e6 src/lib-storage/index/dbox-single/sdbox-storage.c
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c	Thu Dec 08 09:32:03 2011 +0200
@@ -287,8 +287,8 @@
 		if (mailbox_open(box) < 0)
 			return -1;
 	}
-	if (update->cache_fields != NULL)
-		index_storage_mailbox_update_cache_fields(box, update);
+	if (update->cache_updates != NULL)
+		index_storage_mailbox_update_cache(box, update);
 	return sdbox_mailbox_create_indexes(box, update, NULL);
 }
 
diff -r ddfe3a0f75e6 src/lib-storage/index/index-status.c
--- a/src/lib-storage/index/index-status.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-storage/index/index-status.c	Thu Dec 08 09:32:03 2011 +0200
@@ -94,18 +94,23 @@
 {
 	const struct mail_cache_field *fields;
 	enum mail_cache_decision_type dec;
-	ARRAY_TYPE(const_string) *cache_fields;
+	ARRAY_TYPE(mailbox_cache_field) *cache_fields;
+	struct mailbox_cache_field *cf;
 	unsigned int i, count;
 
 	fields = mail_cache_register_get_list(box->cache,
 					      pool_datastack_create(), &count);
 
-	cache_fields = t_new(ARRAY_TYPE(const_string), 1);
+	cache_fields = t_new(ARRAY_TYPE(mailbox_cache_field), 1);
 	t_array_init(cache_fields, count);
 	for (i = 0; i < count; i++) {
 		dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
-		if (dec != MAIL_CACHE_DECISION_NO)
-			array_append(cache_fields, &fields[i].name, 1);
+		if (dec != MAIL_CACHE_DECISION_NO) {
+			cf = array_append_space(cache_fields);
+			cf->name = fields[i].name;
+			cf->decision = fields[i].decision;
+			cf->last_used = fields[i].last_used;
+		}
 	}
 	metadata_r->cache_fields = cache_fields;
 }
diff -r ddfe3a0f75e6 src/lib-storage/index/index-storage.c
--- a/src/lib-storage/index/index-storage.c	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-storage/index/index-storage.c	Thu Dec 08 09:32:03 2011 +0200
@@ -353,10 +353,10 @@
 		mail_index_alloc_cache_unref(&box->index);
 }
 
-void index_storage_mailbox_update_cache_fields(struct mailbox *box,
-					       const struct mailbox_update *update)
+void index_storage_mailbox_update_cache(struct mailbox *box,
+					const struct mailbox_update *update)
 {
-	const char *const *field_names = update->cache_fields;
+	const struct mailbox_cache_field *updates = update->cache_updates;
 	ARRAY_DEFINE(new_fields, struct mail_cache_field);
 	const struct mail_cache_field *old_fields;
 	struct mail_cache_field field;
@@ -368,28 +368,28 @@
 
 	/* There shouldn't be many fields, so don't worry about O(n^2). */
 	t_array_init(&new_fields, 32);
-	for (i = 0; field_names[i] != NULL; i++) {
+	for (i = 0; updates[i].name != NULL; i++) {
 		/* see if it's an existing field */
 		for (j = 0; j < old_count; j++) {
-			if (strcmp(field_names[i], old_fields[j].name) == 0)
+			if (strcmp(updates[i].name, old_fields[j].name) == 0)
 				break;
 		}
 		if (j != old_count) {
 			field = old_fields[j];
-			if (field.decision == MAIL_CACHE_DECISION_NO)
-				field.decision = MAIL_CACHE_DECISION_TEMP;
-			array_append(&new_fields, &field, 1);
-		} else if (strncmp(field_names[i], "hdr.", 4) == 0) {
+		} else if (strncmp(updates[i].name, "hdr.", 4) == 0) {
 			/* new header */
 			memset(&field, 0, sizeof(field));
-			field.name = field_names[i];
+			field.name = updates[i].name;
 			field.type = MAIL_CACHE_FIELD_HEADER;
-			field.decision = MAIL_CACHE_DECISION_TEMP;
-			array_append(&new_fields, &field, 1);
 		} else {
 			/* new unknown field. we can't do anything about
 			   this since we don't know its type */
+			continue;
 		}
+		field.decision = updates[i].decision;
+		if (updates[i].last_used != (time_t)-1)
+			field.last_used = updates[i].last_used;
+		array_append(&new_fields, &field, 1);
 	}
 	if (array_count(&new_fields) > 0) {
 		mail_cache_register_fields(box->cache,
@@ -408,8 +408,8 @@
 
 	if (mailbox_open(box) < 0)
 		return -1;
-	if (update->cache_fields != NULL)
-		index_storage_mailbox_update_cache_fields(box, update);
+	if (update->cache_updates != NULL)
+		index_storage_mailbox_update_cache(box, update);
 
 	/* make sure we get the latest index info */
 	(void)mail_index_refresh(box->index);
@@ -641,7 +641,7 @@
 {
 	T_BEGIN {
 		struct mailbox_metadata src_metadata;
-		const char *const *namep;
+		const struct mailbox_cache_field *field;
 		buffer_t *buf;
 
 		if (mailbox_get_metadata(src_mail->box,
@@ -650,9 +650,9 @@
 			i_unreached();
 
 		buf = buffer_create_dynamic(pool_datastack_create(), 1024);
-		array_foreach(src_metadata.cache_fields, namep) {
+		array_foreach(src_metadata.cache_fields, field) {
 			mail_copy_cache_field(ctx, src_mail, dest_seq,
-					      *namep, buf);
+					      field->name, buf);
 		}
 	} T_END;
 }
diff -r ddfe3a0f75e6 src/lib-storage/index/index-storage.h
--- a/src/lib-storage/index/index-storage.h	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-storage/index/index-storage.h	Thu Dec 08 09:32:03 2011 +0200
@@ -69,8 +69,8 @@
 void index_storage_mailbox_free(struct mailbox *box);
 int index_storage_mailbox_update(struct mailbox *box,
 				 const struct mailbox_update *update);
-void index_storage_mailbox_update_cache_fields(struct mailbox *box,
-					       const struct mailbox_update *update);
+void index_storage_mailbox_update_cache(struct mailbox *box,
+					const struct mailbox_update *update);
 int index_storage_mailbox_delete(struct mailbox *box);
 int index_storage_mailbox_delete_dir(struct mailbox *box, bool mailbox_deleted);
 int index_storage_mailbox_rename(struct mailbox *src, struct mailbox *dest,
diff -r ddfe3a0f75e6 src/lib-storage/mail-storage.h
--- a/src/lib-storage/mail-storage.h	Thu Dec 08 09:30:14 2011 +0200
+++ b/src/lib-storage/mail-storage.h	Thu Dec 08 09:32:03 2011 +0200
@@ -225,12 +225,20 @@
 	unsigned int allow_new_keywords:1;
 };
 
+struct mailbox_cache_field {
+	const char *name;
+	int decision; /* enum mail_cache_decision_type */
+	/* last_used is unchanged, if it's (time_t)-1 */
+	time_t last_used;
+};
+ARRAY_DEFINE_TYPE(mailbox_cache_field, struct mailbox_cache_field);
+
 struct mailbox_metadata {
 	guid_128_t guid;
 	/* 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;
+	const ARRAY_TYPE(mailbox_cache_field) *cache_fields;
 	/* Fields that should be precached */
 	enum mail_fetch_field precache_fields;
 };
@@ -242,8 +250,8 @@
 	uint32_t min_next_uid;
 	uint32_t min_first_recent_uid;
 	uint64_t min_highest_modseq;
-	/* Add these fields to be temporarily cached, if they aren't already. */
-	const char *const *cache_fields;
+	/* Modify caching decisions, terminated by name=NULL */
+	const struct mailbox_cache_field *cache_updates;
 };
 
 struct mail_transaction_commit_changes {
