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.