Example #1
0
static int
sfs_getdirentry(struct inode *node, struct iobuf *iob) {
    struct sfs_disk_entry *entry;
    if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) {
        return -E_NO_MEM;
    }

    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    int ret, slot;
    off_t offset = iob->io_offset;
    if (offset < 0 || offset % sfs_dentry_size != 0) {
        kfree(entry);
        return -E_INVAL;
    }
    if ((slot = offset / sfs_dentry_size) > sin->din->blocks) {
        kfree(entry);
        return -E_NOENT;
    }
    lock_sin(sin);
    if ((ret = sfs_getdirentry_sub_nolock(sfs, sin, slot, entry)) != 0) {
        unlock_sin(sin);
        goto out;
    }
    unlock_sin(sin);
    ret = iobuf_move(iob, entry->name, sfs_dentry_size, 1, NULL);
out:
    kfree(entry);
    return ret;
}
Example #2
0
// Lock the given inode.
// Reads the inode from disk if necessary.
static void
sfs_ilock(struct inode *ip)
{
  struct sfs_inode *sin = vop_info(ip, sfs_inode);
  struct buf *bp;
  struct sfs_dinode *dip;

  if(sin == 0 || sin->ref < 1)
    panic("ilock");

  acquire(&icache.lock);
  while(sin->flags & I_BUSY)
    sleep(ip, &icache.lock);
  sin->flags |= I_BUSY;
  release(&icache.lock);
  
  if(!(sin->flags & I_VALID)){
//    cprintf("dev=%d, inum=%d\n", sin->dev, sin->inum);
    bp = bread(sin->dev, IBLOCK(sin->inum));
    dip = (struct sfs_dinode*)bp->data + sin->inum%IPB;
    sin->type = dip->type;
    sin->major = dip->major;
    sin->minor = dip->minor;
    sin->nlink = dip->nlink;
    sin->size = dip->size;
    memmove(sin->addrs, dip->addrs, sizeof(sin->addrs));
    brelse(bp);
    sin->flags |= I_VALID;
    if(sin->type == 0)
      panic("ilock: no type");
  }
}
Example #3
0
static int pipe_inode_ioctl(struct inode * node, int op, void *data)
{
  struct pipe_inode *pin = vop_info(node, pipe_inode);
  if(op & 04000) pin->no_block = 1;
  else pin->no_block = 0;
  return 0;
}
Example #4
0
// PAGEBREAK!
// Write data to inode.
int
sfs_writei(struct inode *ip, char *src, uint off, uint n)
{
  struct sfs_inode *sin = vop_info(ip, sfs_inode);
  uint tot, m;
  struct buf *bp;

  if(sin->type == T_DEV){
    if(sin->major < 0 || sin->major >= NDEV || !devsw[sin->major].write)
      return -1;
    return devsw[sin->major].write(ip, src, n);
  }

  if(off > sin->size || off + n < off)
    return -1;
  if(off + n > MAXFILE*BSIZE)
    return -1;

  for(tot=0; tot<n; tot+=m, off+=m, src+=m){
    bp = bread(sin->dev, bmap(sin, off/BSIZE));
    m = min(n - tot, BSIZE - off%BSIZE);
    memmove(bp->data + off%BSIZE, src, m);
    log_write(bp);
    brelse(bp);
  }

  if(n > 0 && off > sin->size){
    sin->size = off;
    sfs_iupdate(ip);
  }
  return n;
}
Example #5
0
//PAGEBREAK!
// Read data from inode.
int
sfs_readi(struct inode *ip, char *dst, uint off, uint n)
{
//  cprintf("enter sfs_readi\n");
  struct sfs_inode *sin = vop_info(ip, sfs_inode);
  uint tot, m;
  struct buf *bp;
//  cprintf("inum = %d , type = %d  \n", sin->inum, sin->type);
  if(sin->type == T_DEV){
    if(sin->major < 0 || sin->major >= NDEV || !devsw[sin->major].read)
      return -1;
    return devsw[sin->major].read(ip, dst, n);
  }

  if(off > sin->size || off + n < off)
    return -1;
  if(off + n > sin->size)
    n = sin->size - off;

  for(tot=0; tot<n; tot+=m, off+=m, dst+=m){
    bp = bread(sin->dev, bmap(sin, off/BSIZE));
    m = min(n - tot, BSIZE - off%BSIZE);
    memmove(dst, bp->data + off%BSIZE, m);
    brelse(bp);
  }
  return n;
}
Example #6
0
static int
sfs_dirent_create_inode(struct sfs_fs *sfs, uint16_t type, struct inode **node_store) {
    struct sfs_disk_inode *din;
    if ((din = kmalloc(sizeof(struct sfs_disk_inode))) == NULL) {
        return -E_NO_MEM;
    }
    memset(din, 0, sizeof(struct sfs_disk_inode));
    din->type = type;

    int ret;
    uint32_t ino;
    if ((ret = sfs_block_alloc(sfs, &ino)) != 0) {
        goto failed_cleanup_din;
    }
    struct inode *node;
    if ((ret = sfs_create_inode(sfs, din, ino, &node)) != 0) {
        goto failed_cleanup_ino;
    }
    lock_sfs_fs(sfs);
    {
        sfs_set_links(sfs, vop_info(node, sfs_inode));
    }
    unlock_sfs_fs(sfs);
    *node_store = node;
    return 0;

failed_cleanup_ino:
    sfs_block_free(sfs, ino);
failed_cleanup_din:
    kfree(din);
    return ret;
}
Example #7
0
static int
sfs_mkdir_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name) {
    int ret, slot;
    if ((ret = sfs_dirent_search_nolock(sfs, sin, name, NULL, NULL, &slot)) != -E_NOENT) {
        return (ret != 0) ? ret : -E_EXISTS;
    }
    struct inode *link_node;
    if ((ret = sfs_dirent_create_inode(sfs, SFS_TYPE_DIR, &link_node)) != 0) {
        return ret;
    }
    struct sfs_inode *lnksin = vop_info(link_node, sfs_inode);
    if ((ret = sfs_dirent_link_nolock(sfs, sin, slot, lnksin, name)) != 0) {
        assert(lnksin->din->nlinks == 0);
        assert(inode_ref_count(link_node) == 1 && inode_open_count(link_node) == 0);
        goto out;
    }

    /* set parent */
    sfs_dirinfo_set_parent(lnksin, sin);

    /* add '.' link to itself */
    sfs_nlinks_inc_nolock(lnksin);

    /* add '..' link to parent */
    sfs_nlinks_inc_nolock(sin);

out:
    vop_ref_dec(link_node);
    return ret;
}
Example #8
0
// Truncate inode (discard contents).
// Only called when the inode has no links
// to it (no directory entries referring to it)
// and has no in-memory reference to it (is
// not an open file or current directory).
static void
sfs_itrunc(struct inode *ip)
{
  struct sfs_inode *sin = vop_info(ip, sfs_inode);
  int i, j;
  struct buf *bp;
  uint *a;

  for(i = 0; i < NDIRECT; i++){
    if(sin->addrs[i]){
      bfree(sin->dev, sin->addrs[i]);
      sin->addrs[i] = 0;
    }
  }
  
  if(sin->addrs[NDIRECT]){
    bp = bread(sin->dev, sin->addrs[NDIRECT]);
    a = (uint*)bp->data;
    for(j = 0; j < NINDIRECT; j++){
      if(a[j])
        bfree(sin->dev, a[j]);
    }
    brelse(bp);
    bfree(sin->dev, sin->addrs[NDIRECT]);
    sin->addrs[NDIRECT] = 0;
  }

  sin->size = 0;
  sfs_iupdate(ip);
}
Example #9
0
int linux_devfile_write(int fd, void *base, size_t len, size_t * copied_store)
{
	int ret = -E_INVAL;
	struct file *file;
	/* use 8byte int, in case of 64bit off_t
	 * config in linux kernel */
	int64_t offset;
	if ((ret = fd2file(fd, &file)) != 0) {
		return 0;
	}

	if (!file->writable) {
		return -E_INVAL;
	}
	filemap_acquire(file);
	offset = file->pos;
	struct device *dev = vop_info(file->node, device);
	assert(dev);
	ret = dev->d_linux_write(dev, base, len, (size_t *) & offset);
	if (ret >= 0) {
		*copied_store = (size_t) ret;
		file->pos += ret;
		ret = 0;
	}
	filemap_release(file);
	return ret;
}
Example #10
0
File: dev.c Project: spinlock/ucore
/*
 * Called for each open().
 *
 * We reject O_CREAT | O_TRUNC | O_EXCL | O_APPEND
 */
static int
dev_open(struct inode *node, uint32_t open_flags) {
    if (open_flags & (O_CREAT | O_TRUNC | O_EXCL | O_APPEND)) {
        return -E_INVAL;
    }
    struct device *dev = vop_info(node, device);
    return dop_open(dev, open_flags);
}
Example #11
0
// Increment reference count for ip.
// Returns ip to enable ip = idup(ip1) idiom.
struct inode*
sfs_idup(struct inode *ip)
{
  struct sfs_inode *sip = vop_info(ip, sfs_inode);
  acquire(&icache.lock);
  sip->ref++;
  release(&icache.lock);
  return ip;
}
Example #12
0
// Increment reference count for ip.
// Returns ip to enable ip = idup(ip1) idiom.
struct inode*
sfs_link_dec(struct inode *ip)
{
  struct sfs_inode *sip = vop_info(ip, sfs_inode);
  acquire(&icache.lock);
  sip->nlink--;
  release(&icache.lock);
  return ip;
}
Example #13
0
/*
 * Called for each open().
 *
 * We reject O_CREAT | O_TRUNC | O_EXCL | O_APPEND
 */
static int
dev_open(struct inode *node, struct file *filp) {
    if (filp->open_flags & (O_CREAT | O_TRUNC | O_EXCL | O_APPEND)) {
        return -E_INVAL;
    }

    struct device *dev = vop_info(node, device);
    return dop_open(dev, node, filp);
}
Example #14
0
/*
 * sfs_tryseek - Check if seeking to the specified position within the file is legal.
 */
static int
sfs_tryseek(struct inode *node, off_t pos) {
    if (pos < 0 || pos >= SFS_MAX_FILE_SIZE) {
        return -E_INVAL;
    }
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    if (pos > sin->din->size) {
        return vop_truncate(node, pos);
    }
    return 0;
}
Example #15
0
// Copy stat information from inode.
void
sfs_stati(struct inode *ip, struct stat *st)
{
  struct sfs_inode *sin = vop_info(ip, sfs_inode); 
  st->dev = sin->dev;
  st->ino = sin->inum;
  st->type = sin->type;
  st->nlink = sin->nlink;
  st->size = sin->size;
  st->fstype = ip->fstype;
}
Example #16
0
/* linux devfile adaptor */
bool __is_linux_devfile(int fd)
{
	int ret = -E_INVAL;
	struct file *file;
	if ((ret = fd2file(fd, &file)) != 0) {
		return 0;
	}
	if (file->node && check_inode_type(file->node, device)
	    && dev_is_linux_dev(vop_info(file->node, device)))
		return 1;
	return 0;
}
Example #17
0
/*
 * Attempt a seek.
 * For block devices, require block alignment.
 * For character devices, prohibit seeking entirely.
 */
static int
dev_tryseek(struct inode *node, off_t pos) {
    struct device *dev = vop_info(node, device);
    if (dev->d_blocks > 0) {
        if ((pos % dev->d_blocksize) == 0) {
            if (pos >= 0 && pos < dev->d_blocks * dev->d_blocksize) {
                return 0;
            }
        }
    }
    return -E_INVAL;
}
Example #18
0
static int
sfs_link(struct inode *node, const char *name, struct inode *link_node) {
    if (strlen(name) > SFS_MAX_FNAME_LEN) {
        return -E_TOO_BIG;
    }
    if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
        return -E_EXISTS;
    }
    struct sfs_inode *lnksin = vop_info(link_node, sfs_inode);
    if (lnksin->din->type == SFS_TYPE_DIR) {
        return -E_ISDIR;
    }
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    int ret;
    if ((ret = trylock_sin(sin)) == 0) {
        ret = sfs_link_nolock(sfs, sin, lnksin, name);
        unlock_sin(sin);
    }
    return ret;
}
Example #19
0
// Unlock the given inode.
static void
sfs_iunlock(struct inode *ip)
{
  struct sfs_inode *sin = vop_info(ip, sfs_inode);
  if(sin == 0 || !(sin->flags & I_BUSY) || sin->ref < 1)
    panic("iunlock");

  acquire(&icache.lock);
  sin->flags &= ~I_BUSY;
  wakeup(ip);
  release(&icache.lock);
}
Example #20
0
/*
 * sfs_fstat - Return nlinks/block/size, etc. info about a file. The pointer is a pointer to struct stat;
 */
static int
sfs_fstat(struct inode *node, struct stat *stat) {
    int ret;
    memset(stat, 0, sizeof(struct stat));
    if ((ret = vop_gettype(node, &(stat->st_mode))) != 0) {
        return ret;
    }
    struct sfs_disk_inode *din = vop_info(node, sfs_inode)->din;
    stat->st_nlinks = din->nlinks;
    stat->st_blocks = din->blocks;
    stat->st_size = din->size;
    return 0;
}
Example #21
0
/*
 * sfs_create_inode - alloc a inode in memroy, and init din/ino/dirty/reclian_count/sem fields in sfs_inode in inode
 */
static int
sfs_create_inode(struct sfs_fs *sfs, struct sfs_disk_inode *din, uint32_t ino, struct inode **node_store) {
    struct inode *node;
    if ((node = alloc_inode(sfs_inode)) != NULL) {
        vop_init(node, sfs_get_ops(din->type), info2fs(sfs, sfs));
        struct sfs_inode *sin = vop_info(node, sfs_inode);
        sin->din = din, sin->ino = ino, sin->dirty = 0, sin->reclaim_count = 1;
        sem_init(&(sin->sem), 1);
        *node_store = node;
        return 0;
    }
    return -E_NO_MEM;
}
Example #22
0
/*
 * Called for fstat().
 * Set the type and the size.
 * The link count for a device is always 1.
 */
static int
dev_fstat(struct inode *node, struct stat *stat) {
    int ret;
    memset(stat, 0, sizeof(struct stat));
    if ((ret = vop_gettype(node, &(stat->st_mode))) != 0) {
        return ret;
    }
    struct device *dev = vop_info(node, device);
    stat->st_nlinks = 1;
    stat->st_blocks = dev->d_blocks;
    stat->st_size = stat->st_blocks * dev->d_blocksize;
    return 0;
}
Example #23
0
void
dev_init_ashmem(void) {
    struct inode *node;
    if((node = dev_create_inode()) == NULL) {
        panic("null: dev_create_node.\n");
    }
    ashmem_device_init(vop_info(node, device));

    int ret;
    if((ret = vfs_add_dev("ashmem", node, 0)) != 0) {
        panic("ashmem: vfs_add_dev: %e.\n", ret);
    }
}
Example #24
0
void dev_init_stdout(void)
{
	struct inode *node;
	if ((node = dev_create_inode()) == NULL) {
		panic("stdout: dev_create_node.\n");
	}
	stdout_device_init(vop_info(node, device));

	int ret;
	if ((ret = vfs_add_dev("stdout", node, 0)) != 0) {
		panic("stdout: vfs_add_dev: %e.\n", ret);
	}
}
Example #25
0
static int pipe_inode_write(struct inode *node, struct iobuf *iob)
{
	struct pipe_inode *pin = vop_info(node, pipe_inode);
	if (pin->pin_type != PIN_WRONLY) {
		return -E_INVAL;
	}
	size_t ret;
	if ((ret =
	     pipe_state_write(pin->state, iob->io_base, iob->io_resid)) != 0) {
		iobuf_skip(iob, ret);
	}
	return 0;
}
Example #26
0
void
dev_init_disk0(void) {
    struct inode *node;
    if ((node = dev_create_inode()) == NULL) {
        panic("disk0: dev_create_node.\n");
    }
    disk0_device_init(vop_info(node, device));

    int ret;
    if ((ret = vfs_add_dev("disk0", node, 1)) != 0) {
        panic("disk0: vfs_add_dev: %e.\n", ret);
    }
}
Example #27
0
static int
sfs_reclaim(struct inode *node) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    lock_sfs_fs(sfs);

    int ret = -E_BUSY;
    assert(sin->reclaim_count > 0);
    if ((-- sin->reclaim_count) != 0) {
        goto failed_unlock;
    }
    assert(inode_ref_count(node) == 0 && inode_open_count(node) == 0);

    if (sin->din->nlinks == 0) {
        uint32_t nblks;
        for (nblks = sin->din->blocks; nblks != 0; nblks --) {
            sfs_bmap_truncate_nolock(sfs, sin);
        }
    }
    else if (sin->dirty) {
        if ((ret = vop_fsync(node)) != 0) {
            goto failed_unlock;
        }
    }
    
    sfs_remove_links(sin);
    unlock_sfs_fs(sfs);

    if (sin->din->nlinks == 0) {
        sfs_block_free(sfs, sin->ino);
        uint32_t ent;
        if ((ent = sin->din->indirect) != 0) {
            sfs_block_free(sfs, ent);
        }
        if ((ent = sin->din->db_indirect) != 0) {
            int i;
            for (i = 0; i < SFS_BLK_NENTRY; i ++) {
                sfs_bmap_free_sub_nolock(sfs, ent, i);
            }
            sfs_block_free(sfs, ent);
        }
    }
    kfree(sin->din);
    vop_kill(node);
    return 0;

failed_unlock:
    unlock_sfs_fs(sfs);
    return ret;
}
Example #28
0
int linux_devfile_ioctl(int fd, unsigned int cmd, unsigned long arg)
{
	int ret = -E_INVAL;
	struct file *file;
	if ((ret = fd2file(fd, &file)) != 0) {
		return 0;
	}
	filemap_acquire(file);
	struct device *dev = vop_info(file->node, device);
	assert(dev);
	ret = dev->d_linux_ioctl(dev, cmd, arg);
	filemap_release(file);
	return ret;
}
Example #29
0
void *linux_devfile_mmap2(void *addr, size_t len, int prot, int flags, int fd, size_t pgoff)
{
  int ret = -E_INVAL;
  struct file *file;
  if ((ret = fd2file(fd, &file)) != 0) {
    return NULL;
  }
  filemap_acquire(file);
  struct device *dev = vop_info(file->node, device);
  assert(dev);
  void* r = dev->d_linux_mmap(dev, addr, len, prot, flags, pgoff);
  filemap_release(file);
  return r;
}
Example #30
0
struct inode*
sfs_create_inode(struct inode *dirnode, short type, short major, short minor, char* name){
//  cprintf("enter sfs_create_inode\n");
  struct sfs_inode *sdirnode = vop_info(dirnode, sfs_inode);
  struct inode *ip = sfs_ialloc(dirnode, sdirnode->dev, type);
  struct sfs_inode *sip = vop_info(ip, sfs_inode);
  vop_ilock(ip);
  sip->major = major;
  sip->minor = minor;
  sip->nlink = 1;
  vop_iupdate(ip);
  if(type == T_DIR){  // Create . and .. entries.
    vop_link_inc(dirnode);  // for ".."
    vop_iupdate(dirnode);
    // No ip->nlink++ for ".": avoid cyclic ref count.
    if(vop_dirlink(ip, ".", ip) < 0 || vop_dirlink(ip, "..", dirnode) < 0)
      panic("create dots");
  }

  if(vop_dirlink(dirnode, name, ip) < 0)
    panic("create: dirlink");
  return ip;
}