static void calculate_refcounts(int *counts, vnode_t *vnode) { int ret; counts[vnode->vn_vno]++; dbg(DBG_S5FS, "calculate_refcounts: Incrementing count of inode %d to" " %d\n", vnode->vn_vno, counts[vnode->vn_vno]); /* * We only consider the children of this directory if this is the * first time we have seen it. Otherwise, we would recurse forever. */ if (counts[vnode->vn_vno] == 1 && S_ISDIR(vnode->vn_mode)) { int offset = 0; struct dirent d; vnode_t *child; while (0 < (ret = s5fs_readdir(vnode, offset, &d))) { /* * We don't count '.', because we don't increment the * refcount for this (an empty directory only has a * link count of 1). */ if (0 != strcmp(d.d_name, ".")) { child = vget(vnode->vn_fs, d.d_ino); calculate_refcounts(counts, child); vput(child); } offset += ret; } KASSERT(ret == 0); } }
/* * s5fs_check_refcounts: * This will check the refcounts for the filesystem. It will ensure that that * the expected number of refcounts will equal the actual number. * param *fs: the pointer to the file system object * return: 0 on success; negative number on failure */ int s5fs_check_refcounts(fs_t *fs) { s5fs_t* s5fs = (s5fs_t *)fs->fs_i; int* refcounts; int ret = 0; uint32_t i; /* malloc the ref mem */ refcounts = kmalloc(s5fs->s5f_super->s5s_num_inodes * sizeof(int)); KASSERT(refcounts); memset(refcounts, 0, s5fs->s5f_super->s5s_num_inodes * sizeof(int)); calculate_refcounts(refcounts, fs->fs_root); --refcounts[fs->fs_root->vn_vno]; /* the call on the preceding line * caused this to be incremented * not because another fs link to * it was discovered */ dbg(DBG_PRINT, "Checking refcounts of s5fs filesystem on block " "device with major %d, minor %d\n", MAJOR(s5fs->s5f_bdev->bd_id), MINOR(s5fs->s5f_bdev->bd_id)); for (i = 0; i < s5fs->s5f_super->s5s_num_inodes; i++) { vnode_t *vn; if (!refcounts[i]) continue; vn = vget(fs, i); KASSERT(vn); if (refcounts[i] != VNODE_TO_S5INODE(vn)->s5_linkcount - 1) { dbg(DBG_PRINT, " Inode %d, expecting %d, found %d\n", i, refcounts[i], VNODE_TO_S5INODE(vn)->s5_linkcount - 1); ret = -1; } vput(vn); } dbg(DBG_PRINT, "Refcount check of s5fs filesystem on block " "device with major %d, minor %d completed %s.\n", MAJOR(s5fs->s5f_bdev->bd_id), MINOR(s5fs->s5f_bdev->bd_id), (ret ? "UNSUCCESSFULLY" : "successfully")); kfree(refcounts); return ret; }