Beispiel #1
0
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);
}
Beispiel #2
0
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;
}