void invalidate_buffer(struct bufpool *pool, vfs_blkno_t blkno) { struct buf *buf; // If buffer is not in cache we are finished buf = lookup_buffer(pool, blkno); if (!buf) return; // Mark buffer as invalid and release it mark_buffer_invalid(buf); release_buffer(pool, buf); }
int delete_dir_entry(struct inode *dir, char *name, int len) { unsigned int block; vfs_blkno_t blk; vfs_blkno_t lastblk; struct buf *buf; char *p; struct dentry *de; struct dentry *prevde; struct dentry *nextde; if (len <= 0 || len >= MAXPATH) return -1; if (!VFS_S_ISDIR(dir->desc->mode)) return -1; for (block = 0; block < dir->desc->blocks; block++) { blk = get_inode_block(dir, block); buf = get_buffer(dir->fs->cache, blk); if (!buf) return -1; p = buf->data; prevde = NULL; while (p < buf->data + dir->fs->blocksize) { de = (struct dentry *) p; if (fnmatch(name, len, de->name, de->namelen)) { if (prevde) { // Merge entry with previous entry prevde->reclen += de->reclen; memset(de, 0, sizeof(struct dentry) + NAME_ALIGN_LEN(de->namelen)); mark_buffer_updated(buf); } else if (de->reclen == dir->fs->blocksize) { // Block is empty, swap this block with last block and truncate if (block != dir->desc->blocks - 1) { lastblk = get_inode_block(dir, dir->desc->blocks - 1); set_inode_block(dir, block, lastblk); set_inode_block(dir, dir->desc->blocks - 1, buf->blkno); } truncate_inode(dir, dir->desc->blocks - 1); dir->desc->size -= dir->fs->blocksize; mark_buffer_invalid(buf); } else { // Merge with next entry nextde = (struct dentry *) (p + de->reclen); de->ino = nextde->ino; de->reclen += nextde->reclen; de->namelen = nextde->namelen; memcpy(de->name, nextde->name, nextde->namelen); // TODO: should be memmove? mark_buffer_updated(buf); } release_buffer(dir->fs->cache, buf); dir->desc->mtime = time(NULL); mark_inode_dirty(dir); return 0; } prevde = de; p += de->reclen; } release_buffer(dir->fs->cache, buf); } return -1; }