ftp.nice.ch/pub/next/unix/disk/ufs-NeXT.0.3.s.tar.gz#/linux/fs/ufs/file.c

This is file.c in view mode; [Download] [Up]

/*
 *  linux/fs/ufs/file.c
 *
 *  Copyright (C) 1994 Yossi Gottlieb (yogo@math.tau.ac.il)
 *
 *  Based on code and information:
 *	BSD code,  Copyright (c) 1982, 1986 Regents of the University of California.
 *		   All rights reserved.
 *	linux/fs/minix	Copyright (C) 1991, 1992, 1993  Linus Torvalds
 *
 */

#include <linux/fs.h>

#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/locks.h>

#include <asm/system.h>
#include <asm/segment.h>
#include <asm/bitops.h>

#include <linux/ufs_fs.h>
#include "ufs.h"

#define	NBUF	32

int ufs_file_read(struct inode *, struct file *, char *, int);
int ufs_bmap(struct inode *, int block);

struct file_operations ufs_file_operations = {
	NULL,			/* lseek - none */
	ufs_file_read,		/* read - none */
	NULL,			/* write - none */
	NULL,
	NULL,			/* select - none */
	NULL,			/* ioctl - none */
	generic_mmap,		/* mmap - none */
	NULL,			/* open - none */
	NULL,			/* release - none */
	file_fsync,		/* fsync - none */
	NULL,			/* fasync - none */
	NULL,
	NULL
};

struct inode_operations ufs_file_inode_operations = {
	&ufs_file_operations,
	NULL,			/* create - none */
	NULL,			/* lookup - none */
	NULL,			/* link - none */
	NULL,			/* unlink - none */
	NULL,			/* symlink - none */
	NULL,			/* mkdir - none */
	NULL,			/* rmdir - none */
	NULL,			/* mknod - none */
	NULL,			/* rename - none */
	NULL,			/* readlink - none */
	NULL,			/* follow_link - none */
	ufs_bmap,		/* bmap - wrapper for ufs_blknum */
	NULL,			/* truncate - none */
	NULL,			/* permission - none */
	NULL			/* smap - none */
};


int ufs_bmap(struct inode *inode, int block)
{
	return fsbtodb(&inode->i_sb->u.ufs_sb, ufs_blknum(inode, block));
}

int ufs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
{
	int read,left,chars;
	int block, blocks, offset, blk, bfrag, bmaxfrag;
	int bhrequest, uptodate;
	struct buffer_head ** bhb, ** bhe;
	struct buffer_head * bhreq[NBUF];
	struct buffer_head * buflist[NBUF];
	struct ufs_sb_info *sb = &inode->i_sb->u.ufs_sb;
	unsigned int size;

	if (!inode) {
		printk("ufs_file_read: inode = NULL\n");
		return -EINVAL;
	}
	if (!S_ISREG(inode->i_mode)) {
		printk("ufs_file_read: mode = %07o\n",inode->i_mode);
		return -EINVAL;
	}
	offset = filp->f_pos;
	size = inode->i_size;
	if (offset > size)
		left = 0;
	else
		left = size - offset;
	if (left > count)
		left = count;
	if (left <= 0)
		return 0;
	read = 0;
	block = lblkno(sb, offset);
	bfrag = numfrags(sb, offset & (sb->fs_bsize-1));
	offset &= sb->fs_fsize-1;
	size = blkroundup(sb, size);
	blocks = lblkno(sb, blkroundup(sb, left));
	bhb = bhe = buflist;
	if (filp->f_reada) {
	        if (blocks < read_ahead[MAJOR(inode->i_dev)] / BLOCK_SIZE >> 9)
		  blocks = read_ahead[MAJOR(inode->i_dev)] / BLOCK_SIZE >> 9;
		if (block + blocks > size)
			blocks = size - block;
	}

	bmaxfrag = sb->fs_frag;

#ifdef UFS_DEBUG
	printk("ufs_file_read: block=%d,blocks=%d,size=%d,offset=%d,bmaxfrag=%d,left=%d\n",
			       block,blocks,size,offset,bmaxfrag,left);
#endif

	do {
		bhrequest = 0;
		uptodate = 1;
		while (blocks) {
			if (!--blocks)
				bmaxfrag = bfrag + numfrags(sb, fragroundup(sb, left));
			else
				bmaxfrag = sb->fs_frag - bfrag;

			blk = ufs_blknum(inode, blkstofrags(sb, block));
			if (blk > 0) {
				blk = fsbtodb(sb, blk);
				blk += fsbtodb(sb, bfrag);
			}

#ifdef UFS_DEBUG
			printk("ufs_file_read: blk=%d, bfrag=%d, bmaxfrag=%d\n", blk, bfrag, bmaxfrag);
#endif
			while (bfrag < bmaxfrag) {
				if (blk == -1)
					*bhb = NULL;
				else
					*bhb = getblk(inode->i_sb->s_dev, sb->fs_block_base + blk++, BLOCK_SIZE);

				if (*bhb && !(*bhb)->b_uptodate) {
					uptodate = 0;
					bhreq[bhrequest++] = *bhb;
				}
				bfrag += dbtofsb(sb, 1);

				if (++bhb == &buflist[NBUF])
					bhb = buflist;
				if (*bhb == *bhe)
					break;
			}
			if (bfrag >= bmaxfrag) {
				bfrag = 0;
				block++;
#ifdef UFS_DEBUG
				printk("ufs_file_read: finished block %d\n", block);
#endif
			} else {
				blocks++;
#ifdef UFS_DEBUG
				printk("ufs_file_read: unfinished block %d, frag %d\n", block, bfrag);
#endif
			}
			/* 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 < BLOCK_SIZE - offset)
				chars = left;
			else
				chars = BLOCK_SIZE - 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;
	return read;
}


These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.