Exemple #1
0
static int 
xiafs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
{
    int read, left, chars;
    int zone_nr, zones, f_zones, offset;
    int bhrequest, uptodate;
    struct buffer_head ** bhb, ** bhe;
    struct buffer_head * bhreq[NBUF];
    struct buffer_head * buflist[NBUF];

    if (!inode) {
        printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
	return -EINVAL;
    }
    if (!S_ISREG(inode->i_mode)) {
        printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
	return -EINVAL;
    }
    offset = filp->f_pos;
    left = inode->i_size - offset;
    if (left > count)
	left = count;
    if (left <= 0)
	return 0;
    read = 0;
    zone_nr = offset >> XIAFS_ZSIZE_BITS(inode->i_sb);
    offset &= XIAFS_ZSIZE(inode->i_sb) -1 ;
    f_zones =(inode->i_size+XIAFS_ZSIZE(inode->i_sb)-1)>>XIAFS_ZSIZE_BITS(inode->i_sb);
    zones = (left+offset+XIAFS_ZSIZE(inode->i_sb)-1) >> XIAFS_ZSIZE_BITS(inode->i_sb);
    bhb = bhe = buflist;
    if (filp->f_reada) {
        zones += read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
	if (zone_nr + zones > f_zones)
	    zones = f_zones - zone_nr;
    }
Exemple #2
0
static int xiafs_readdir(struct inode * inode, 
		       struct file * filp, struct dirent * dirent, int count)
{
    u_int offset, i;
    struct buffer_head * bh;
    struct xiafs_direct * de;

    if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode))
        return -EBADF;
    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) )
        return -EBADF;
    while (filp->f_pos < inode->i_size) {
        offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1);
	bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0);
	if (!bh) {
	    filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset;
	    continue;
	}
	de = (struct xiafs_direct *) (offset + bh->b_data);
	while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
	    if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
		de->d_rec_len < 12 || 
		(char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data ||
		de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len ||
		de->d_name_len > _XIAFS_NAME_LEN ||
		de->d_name[de->d_name_len] ) {
	        printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
		brelse(bh);
		return 0;
	    }  
	    offset += de->d_rec_len;
	    filp->f_pos += de->d_rec_len;
	    if (de->d_ino) {
	        for (i = 0; i < de->d_name_len ; i++)
		    put_fs_byte(de->d_name[i],i+dirent->d_name);
		put_fs_byte(0,i+dirent->d_name);
		put_fs_long(de->d_ino,&dirent->d_ino);
		put_fs_word(i,&dirent->d_reclen);
		brelse(bh);
		if (!IS_RDONLY (inode)) {
		    inode->i_atime=CURRENT_TIME;		    
		    inode->i_dirt=1;
		}
		return i;
	    }
	    de = (struct xiafs_direct *) (offset + bh->b_data);
	}
	brelse(bh);
	if (offset > XIAFS_ZSIZE(inode->i_sb)) {
	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
	    return 0;
	}
    }
    if (!IS_RDONLY (inode)) {
	inode->i_atime=CURRENT_TIME;		    
	inode->i_dirt=1;
    }
    return 0;
}
Exemple #3
0
/*
 * routine to check that the specified directory is empty (for rmdir)
 */
static int empty_dir(struct inode * inode)
{
    int i, zones, offset;
    struct buffer_head * bh;
    struct xiafs_direct * de;

    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb)-1) ) {
        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
	return 1;
    }

    zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
    for (i=0; i < zones; i++) {
        bh =  xiafs_bread(inode, i, 0);
	if (!i) {
	    if (!bh) {
	        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
		return 1;
	    }
	    de=(struct xiafs_direct *)bh->b_data;
	    if (de->d_ino != inode->i_ino || strcmp(".", de->d_name) ||
		    de->d_rec_len != 12 ) {
	        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
		brelse(bh);
		return 1;	 
	    }
	    de=(struct xiafs_direct *)(12 + bh->b_data);
	    if (!de->d_ino || strcmp("..", de->d_name)) {
	    	printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
		brelse(bh);
		return 1;
	    }
	    offset=de->d_rec_len+12;
	}
	else
	    offset = 0;
	if (!bh)
	    continue;
	while (offset < XIAFS_ZSIZE(inode->i_sb)) {
	    de=(struct xiafs_direct *)(bh->b_data+offset);
	    if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
		de->d_rec_len < 12 || 
		(char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
		de->d_name_len + 8 > de->d_rec_len ||
		de->d_name[de->d_name_len]) {
	        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
		brelse(bh);
		return 1;
	    }
	    if (de->d_ino) {
	        brelse(bh);
		return 0;
	    }
	    offset+=de->d_rec_len;
	}
	brelse(bh);
    }
    return 1;
}
Exemple #4
0
/*
 *	xiafs_find_entry()
 *
 * finds an entry in the specified directory with the wanted name. It
 * returns the cache buffer in which the entry was found, and the entry
 * itself (as a parameter - res_dir). It does NOT read the inode of the
 * entry - you'll have to do that yourself if you want to.
 */
static struct buffer_head * 
xiafs_find_entry(struct inode * inode, const char * name, int namelen, 
	       struct xiafs_direct ** res_dir, struct xiafs_direct ** res_pre)
{
    int i, zones, pos;
    struct buffer_head * bh;
    struct xiafs_direct * dep, * dep_pre;

    *res_dir = NULL;
    if (!inode)
        return NULL;
    if (namelen > _XIAFS_NAME_LEN)
        return NULL;

    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1)) {
        printk("XIA-FS: bad dir size (%s %d)\n", WHERE_ERR);
	return NULL;
    }
    zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
    for (i=0; i < zones; i++ ) {
        bh = xiafs_bread(inode, i, 0);
	if (!bh)
	    continue;
	dep_pre=dep=(struct xiafs_direct *)bh->b_data;
	if (!i && (dep->d_rec_len != 12 || !dep->d_ino || 
		   dep->d_name_len != 1 || strcmp(dep->d_name, "."))) {
	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
	    brelse(bh);
	    return NULL;
	}
	pos = 0;
	while ( pos < XIAFS_ZSIZE(inode->i_sb) ) {
	    if (dep->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
		dep->d_rec_len < 12 || 
		dep->d_rec_len+(char *)dep > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
		dep->d_name_len + 8 > dep->d_rec_len || dep->d_name_len <= 0 ||
		dep->d_name[dep->d_name_len] ) {
	        brelse(bh);
		return NULL;
	    }
	    if (xiafs_match(namelen, name, dep)) {
	        *res_dir=dep;
		if (res_pre) 
		    *res_pre=dep_pre;
		return bh;
	    }
	    pos += dep->d_rec_len;
	    dep_pre=dep;
	    dep=(struct xiafs_direct *)(bh->b_data + pos);
	}
	brelse(bh);
	if (pos > XIAFS_ZSIZE(inode->i_sb)) {
	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
	    return NULL;
	}
    }
    return NULL;
}
Exemple #5
0
static int xiafs_readdir(struct inode * inode, struct file * filp,
	void * dirent, filldir_t filldir)
{
    u_int offset, i;
    struct buffer_head * bh;
    struct xiafs_direct * de;

    if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode))
        return -EBADF;
    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) )
        return -EBADF;
    while (filp->f_pos < inode->i_size) {
        offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1);
	bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0);
	if (!bh) {
	    filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset;
	    continue;
	}
	for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) {
	    de = (struct xiafs_direct *) (bh->b_data + i);
	    if (!de->d_rec_len)
		break;
	    i += de->d_rec_len;
	}
	offset = i;
	de = (struct xiafs_direct *) (offset + bh->b_data);
	
	while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
	    if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
		de->d_rec_len < 12 || 
		(char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data ||
		de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len ||
		de->d_name_len > _XIAFS_NAME_LEN ||
		de->d_name[de->d_name_len] ) {
	        printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
		brelse(bh);
		return 0;
	    }  
	    if (de->d_ino) {
		if (!IS_RDONLY (inode)) {
		    inode->i_atime=CURRENT_TIME;
		    inode->i_dirt=1;
		}
		if (filldir(dirent, de->d_name, de->d_name_len, filp->f_pos, de->d_ino) < 0) {
		    brelse(bh);
		    return 0;
		}
	    }
	    offset += de->d_rec_len;
	    filp->f_pos += de->d_rec_len;
	    de = (struct xiafs_direct *) (offset + bh->b_data);
	}
	brelse(bh);
	if (offset > XIAFS_ZSIZE(inode->i_sb)) {
	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
	    return 0;
	}
    }
    if (!IS_RDONLY (inode)) {
	inode->i_atime=CURRENT_TIME;		    
	inode->i_dirt=1;
    }
    return 0;
}
Exemple #6
0
static int 
xiafs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
{
    int read, left, chars;
    int zone_nr, zones, f_zones, offset;
    int bhrequest, uptodate;
    struct buffer_head ** bhb, ** bhe;
    struct buffer_head * bhreq[NBUF];
    struct buffer_head * buflist[NBUF];

    if (!inode) {
        printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
	return -EINVAL;
    }
    if (!S_ISREG(inode->i_mode)) {
        printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
	return -EINVAL;
    }
    offset = filp->f_pos;
    left = inode->i_size - offset;
    if (left > count)
	left = count;
    if (left <= 0)
	return 0;
    read = 0;
    zone_nr = offset >> XIAFS_ZSIZE_BITS(inode->i_sb);
    offset &= XIAFS_ZSIZE(inode->i_sb) -1 ;
    f_zones =(inode->i_size+XIAFS_ZSIZE(inode->i_sb)-1)>>XIAFS_ZSIZE_BITS(inode->i_sb);
    zones = (left+offset+XIAFS_ZSIZE(inode->i_sb)-1) >> XIAFS_ZSIZE_BITS(inode->i_sb);
    bhb = bhe = buflist;
    if (filp->f_reada) {
        if(zones < read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb)))
	  zones = read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
	if (zone_nr + zones > f_zones)
	    zones = f_zones - zone_nr;
    }

    /* We do this in a two stage process.  We first try and request
       as many blocks as we can, then we wait for the first one to
       complete, and then we try and wrap up as many as are actually
       done.  This routine is rather generic, in that it can be used
       in a filesystem by substituting the appropriate function in
       for getblk.
       
       This routine is optimized to make maximum use of the various
       buffers and caches. */

    do {
        bhrequest = 0;
	uptodate = 1;
	while (zones--) {
	    *bhb = xiafs_getblk(inode, zone_nr++, 0);
	    if (*bhb && !(*bhb)->b_uptodate) {
	        uptodate = 0;
		bhreq[bhrequest++] = *bhb;
	    }

	    if (++bhb == &buflist[NBUF])
	        bhb = buflist;
	    
	    /* If the block we have on hand is uptodate, go ahead
	       and complete processing. */
	    if (uptodate)
	        break;
	    if (bhb == bhe)
	        break;
	}

	/* Now request them all */
	if (bhrequest)
	    ll_rw_block(READ, bhrequest, bhreq);

	do { /* Finish off all I/O that has actually completed */
	    if (*bhe) {
	        wait_on_buffer(*bhe);
		if (!(*bhe)->b_uptodate) {	/* read error? */
		    brelse(*bhe);
		    if (++bhe == &buflist[NBUF])
		      bhe = buflist;
		    left = 0;
		    break;
		}
	    }
	    if (left < XIAFS_ZSIZE(inode->i_sb) - offset)
	        chars = left;
	    else
	        chars = XIAFS_ZSIZE(inode->i_sb) - offset;
	    filp->f_pos += chars;
	    left -= chars;
	    read += chars;
	    if (*bhe) {
	        memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
		brelse(*bhe);
		buf += chars;
	    } else {
	        while (chars-->0)
		    put_fs_byte(0,buf++);
	    }
	    offset = 0;
	    if (++bhe == &buflist[NBUF])
	        bhe = buflist;
	} while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
    } while (left > 0);

/* Release the read-ahead blocks */
    while (bhe != bhb) {
        brelse(*bhe);
	if (++bhe == &buflist[NBUF])
	    bhe = buflist;
    };
    if (!read)
        return -EIO;
    filp->f_reada = 1;
    if (!IS_RDONLY (inode)) {
	inode->i_atime = CURRENT_TIME;
	inode->i_dirt = 1;
    }
    return read;
}
Exemple #7
0
static int 
xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count)
{
    off_t pos;
    int written, c;
    struct buffer_head * bh;
    char * cp;

    if (!inode) {
        printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR);
	return -EINVAL;
    }
    if (!S_ISREG(inode->i_mode)) {
        printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR);
	return -EINVAL;
    }
/*
 * ok, append may not work when many processes are writing at the same time
 * but so what. That way leads to madness anyway.
 */
    if (filp->f_flags & O_APPEND)
        pos = inode->i_size;
    else
        pos = filp->f_pos;
    written = 0;
    while (written < count) {
        bh = xiafs_getblk(inode, pos >> XIAFS_ZSIZE_BITS(inode->i_sb), 1);
	if (!bh) {
	    if (!written)
	        written = -ENOSPC;
	    break;
	}
	c = XIAFS_ZSIZE(inode->i_sb) - (pos & (XIAFS_ZSIZE(inode->i_sb) - 1));
	if (c > count-written)
	    c = count-written;
	if (c != XIAFS_ZSIZE(inode->i_sb) && !bh->b_uptodate) {
	    ll_rw_block(READ, 1, &bh);
	    wait_on_buffer(bh);
	    if (!bh->b_uptodate) {
	        brelse(bh);
		if (!written)
		    written = -EIO;
		break;
	    }
	}
	cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data;
	pos += c;
	if (pos > inode->i_size) {
	    inode->i_size = pos;
	    inode->i_dirt = 1;
	}
	written += c;
	memcpy_fromfs(cp,buf,c);
	buf += c;
	bh->b_uptodate = 1;
	mark_buffer_dirty(bh, 0);
	brelse(bh);
    }
    inode->i_mtime = inode->i_ctime = CURRENT_TIME;
    filp->f_pos = pos;
    inode->i_dirt = 1;

    return written;
}
Exemple #8
0
/*
 *	xiafs_add_entry()
 *
 * adds a file entry to the specified directory, using the same
 * semantics as xiafs_find_entry(). It returns NULL if it failed.
 *
 * NOTE!! The inode part of 'de' is left at 0 - which means you
 * may not sleep between calling this and putting something into
 * the entry, as someone else might have used it while you slept.
 */
static struct buffer_head * xiafs_add_entry(struct inode * dir,
	const char * name, int namelen, struct xiafs_direct ** res_dir, 
	struct xiafs_direct ** res_pre)
{
    int i, pos, offset;
    struct buffer_head * bh;
    struct xiafs_direct * de, * de_pre;

    *res_dir = NULL;
    if (!dir || !namelen || namelen > _XIAFS_NAME_LEN)
        return NULL;

    if (dir->i_size & (XIAFS_ZSIZE(dir->i_sb) - 1)) {
        printk("XIA-FS: bad dir size (%s %d)\n", WHERE_ERR);
	return NULL;
    }
    pos=0;
    for ( ; ; ) {
        bh =  xiafs_bread(dir, pos >> XIAFS_ZSIZE_BITS(dir->i_sb), pos ? 1:0);
	if (!bh)
	    return NULL;
	de_pre=de=(struct xiafs_direct *)bh->b_data;
	if (!pos) {
	    if (de->d_rec_len != 12 || !de->d_ino || de->d_name_len != 1 ||
		strcmp(de->d_name, ".")) {
	        printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
		brelse(bh);
		return NULL;
	    }
	    offset = 12;
	    de_pre=de=(struct xiafs_direct *)(bh->b_data+12);
	} else
	    offset = 0;
	while (offset < XIAFS_ZSIZE(dir->i_sb)) {
	    if (pos >= dir->i_size) {
	        de->d_ino=0;
		de->d_name_len=0;
		de->d_name[0]=0;
		de->d_rec_len=XIAFS_ZSIZE(dir->i_sb);
		dir->i_size += XIAFS_ZSIZE(dir->i_sb);
		dir->i_dirt = 1;
	    } else {
	        if (de->d_ino > dir->i_sb->u.xiafs_sb.s_ninodes ||
		    de->d_rec_len < 12 || 
		    (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(dir->i_sb) ||
		    de->d_name_len + 8 > de->d_rec_len ||
		    de->d_name[de->d_name_len]) {
		    printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
		    brelse(bh);
		    return NULL;
		}
		if (de->d_ino &&
		    RNDUP4(de->d_name_len)+RNDUP4(namelen)+16<=de->d_rec_len) {
		    i=RNDUP4(de->d_name_len)+8;
		    de_pre=de;
		    de=(struct xiafs_direct *)(i+(u_char *)de_pre);
		    de->d_ino=0;
		    de->d_rec_len=de_pre->d_rec_len-i;
		    de_pre->d_rec_len=i;
		}
	    }
	    if (!de->d_ino && RNDUP4(namelen)+8 <= de->d_rec_len) {
		/*
		 * XXX all times should be set by caller upon successful
		 * completion.
		 */
	        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
		dir->i_dirt = 1;
		memcpy(de->d_name, name, namelen);
		de->d_name[namelen]=0;
		de->d_name_len=namelen;
		mark_buffer_dirty(bh, 1);
		*res_dir = de;
		if (res_pre)
		    *res_pre = de_pre;
		return bh;
	    }
	    offset+=de->d_rec_len;
	    de_pre=de;
	    de=(struct xiafs_direct *)(bh->b_data+offset);
	}
	brelse(bh);
	if (offset > XIAFS_ZSIZE(dir->i_sb)) {
	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
	    return NULL;
	}
	pos+=XIAFS_ZSIZE(dir->i_sb);
    }
    return NULL;
}