Rebase master to b117
[zfs.git] / module / zfs / zap_micro.c
index abba427..fbc93b4 100644 (file)
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident  "%Z%%M% %I%     %E% SMI"
-
 #include <sys/spa.h>
 #include <sys/dmu.h>
 #include <sys/zfs_context.h>
@@ -78,8 +76,8 @@ zap_normalize(zap_t *zap, const char *name, char *namenorm)
 
        err = 0;
        (void) u8_textprep_str((char *)name, &inlen, namenorm, &outlen,
-           zap->zap_normflags | U8_TEXTPREP_IGNORE_NULL, U8_UNICODE_LATEST,
-           &err);
+           zap->zap_normflags | U8_TEXTPREP_IGNORE_NULL |
+           U8_TEXTPREP_IGNORE_INVALID, U8_UNICODE_LATEST, &err);
 
        return (err);
 }
@@ -1067,3 +1065,79 @@ zap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs)
        zap_unlockdir(zap);
        return (0);
 }
+
+int
+zap_count_write(objset_t *os, uint64_t zapobj, const char *name, int add,
+    uint64_t *towrite, uint64_t *tooverwrite, uint64_t dn_datablkshift)
+{
+       zap_t *zap;
+       int err = 0;
+
+
+       /*
+        * Since, we don't have a name, we cannot figure out which blocks will
+        * be affected in this operation. So, account for the worst case :
+        * - 3 blocks overwritten: target leaf, ptrtbl block, header block
+        * - 4 new blocks written if adding:
+        *      - 2 blocks for possibly split leaves,
+        *      - 2 grown ptrtbl blocks
+        *
+        * This also accomodates the case where an add operation to a fairly
+        * large microzap results in a promotion to fatzap.
+        */
+       if (name == NULL) {
+               *towrite += (3 + (add ? 4 : 0)) * SPA_MAXBLOCKSIZE;
+               return (err);
+       }
+
+       /*
+        * We lock the zap with adding ==  FALSE. Because, if we pass
+        * the actual value of add, it could trigger a mzap_upgrade().
+        * At present we are just evaluating the possibility of this operation
+        * and hence we donot want to trigger an upgrade.
+        */
+       err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap);
+       if (err)
+               return (err);
+
+       if (!zap->zap_ismicro) {
+               zap_name_t *zn = zap_name_alloc(zap, name, MT_EXACT);
+               if (zn) {
+                       err = fzap_count_write(zn, add, towrite,
+                           tooverwrite);
+                       zap_name_free(zn);
+               } else {
+                       /*
+                        * We treat this case as similar to (name == NULL)
+                        */
+                       *towrite += (3 + (add ? 4 : 0)) * SPA_MAXBLOCKSIZE;
+               }
+       } else {
+               if (!add) {
+                       if (dmu_buf_freeable(zap->zap_dbuf))
+                               *tooverwrite += SPA_MAXBLOCKSIZE;
+                       else
+                               *towrite += SPA_MAXBLOCKSIZE;
+               } else {
+                       /*
+                        * We are here if we are adding and (name != NULL).
+                        * It is hard to find out if this add will promote this
+                        * microzap to fatzap. Hence, we assume the worst case
+                        * and account for the blocks assuming this microzap
+                        * would be promoted to a fatzap.
+                        *
+                        * 1 block overwritten  : header block
+                        * 4 new blocks written : 2 new split leaf, 2 grown
+                        *                      ptrtbl blocks
+                        */
+                       if (dmu_buf_freeable(zap->zap_dbuf))
+                               *tooverwrite += 1 << dn_datablkshift;
+                       else
+                               *towrite += 1 << dn_datablkshift;
+                       *towrite += 4 << dn_datablkshift;
+               }
+       }
+
+       zap_unlockdir(zap);
+       return (err);
+}