]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfscommon/BTree/BTreeNodeReserve.c
xnu-2422.1.72.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / BTree / BTreeNodeReserve.c
index 547a0cf50e5ff3bd8edd4ecdec564491666d8ae5..94577758a1d7da705c82287ad81e34ee460c6e99 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -64,7 +64,7 @@ struct nreserve {
 #define        NR_CACHE 17
 
 #define NR_HASH(btvp, tag) \
-       (&nr_hashtbl[((((int)(btvp)) >> 8) ^ ((int)(tag) >> 4)) & nr_hashmask])
+       (&nr_hashtbl[((((intptr_t)(btvp)) >> 8) ^ ((intptr_t)(tag) >> 4)) & nr_hashmask])
 
 LIST_HEAD(nodereserve, nreserve) *nr_hashtbl;
 
@@ -90,7 +90,7 @@ void
 BTReserveSetup()
 {
        if (sizeof(struct nreserve) != sizeof(cat_cookie_t))
-               panic("BTReserveSetup: nreserve size != opaque struct size");
+               panic("hfs: BTReserveSetup: nreserve size != opaque struct size");
 
        nr_hashtbl = hashinit(NR_CACHE, M_HFSMNT, &nr_hashmask);
 
@@ -153,12 +153,28 @@ BTReserveSpace(FCB *file, int operations, void* data)
        
        if (rsrvNodes > availNodes) {
                u_int32_t reqblks, freeblks, rsrvblks;
+               uint32_t bt_rsrv;
                struct hfsmount *hfsmp;
 
-               /* Try and reserve the last 5% of the disk space for file blocks. */
+               /* 
+                * For UNIX conformance, we try and reserve the MIN of either 5% of 
+                * total file blocks or 10MB worth of blocks, for growing existing 
+                * files.  On non-HFS filesystems, creating a new directory entry may
+                * not cause additional disk space to be allocated, but on HFS, creating
+                * a new entry could cause the b-tree to grow.  As a result, we take 
+                * some precautions here to prevent that on configurations that try to 
+                * satisfy conformance.
+                */
                hfsmp = VTOVCB(btree->fileRefNum);
                rsrvblks = ((u_int64_t)hfsmp->allocLimit * 5) / 100;
-               rsrvblks = MIN(rsrvblks, HFS_MAXRESERVE / hfsmp->blockSize);
+               if (hfsmp->blockSize > HFS_BT_MAXRESERVE) {
+                       bt_rsrv = 1;    
+               }
+               else {
+                       bt_rsrv = (HFS_BT_MAXRESERVE / hfsmp->blockSize);
+               }
+               rsrvblks = MIN(rsrvblks, bt_rsrv);      
+               
                freeblks = hfs_freeblks(hfsmp, 0);
                if (freeblks <= rsrvblks) {
                        /* When running low, disallow adding new items. */
@@ -290,7 +306,7 @@ nr_delete(struct vnode * btvp, struct nreserve *nrp, int *nodecnt)
        lck_mtx_lock(&nr_mutex);
        if (nrp->nr_tag) {
                if ((nrp->nr_tag != tag) || (nrp->nr_btvp != btvp))
-                       panic("nr_delete: invalid NR (%p)", nrp);
+                       panic("hfs: nr_delete: invalid NR (%p)", nrp);
                LIST_REMOVE(nrp, nr_hash);
                *nodecnt = nrp->nr_nodecnt;
                bzero(nrp, sizeof(struct nreserve));