/* * sfs_io_nolock - Rd/Wr a file contentfrom offset position to offset+ length disk blocks<-->buffer (in memroy) * @sfs: sfs file system * @sin: sfs inode in memory * @buf: the buffer Rd/Wr * @offset: the offset of file * @alenp: the length need to read (is a pointer). and will RETURN the really Rd/Wr lenght * @write: BOOL, 0 read, 1 write */ static int sfs_io_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, void *buf, off_t offset, size_t *alenp, bool write) { struct sfs_disk_inode *din = sin->din; assert(din->type != SFS_TYPE_DIR); off_t endpos = offset + *alenp, blkoff; *alenp = 0; // calculate the Rd/Wr end position if (offset < 0 || offset >= SFS_MAX_FILE_SIZE || offset > endpos) { return -E_INVAL; } if (offset == endpos) { return 0; } if (endpos > SFS_MAX_FILE_SIZE) { endpos = SFS_MAX_FILE_SIZE; } if (!write) { if (offset >= din->size) { return 0; } if (endpos > din->size) { endpos = din->size; } } int (*sfs_buf_op)(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset); int (*sfs_block_op)(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks); if (write) { sfs_buf_op = sfs_wbuf, sfs_block_op = sfs_wblock; } else { sfs_buf_op = sfs_rbuf, sfs_block_op = sfs_rblock; } int ret = 0; size_t size, alen = 0; uint32_t ino; uint32_t blkno = offset / SFS_BLKSIZE; // The NO. of Rd/Wr begin block uint32_t nblks = endpos / SFS_BLKSIZE - blkno; // The size of Rd/Wr blocks //LAB8:EXERCISE1 YOUR CODE HINT: call sfs_bmap_load_nolock, sfs_rbuf, sfs_rblock,etc. read different kind of blocks in file /* * (1) If offset isn't aligned with the first block, Rd/Wr some content from offset to the end of the first block * NOTICE: useful function: sfs_bmap_load_nolock, sfs_buf_op * Rd/Wr size = (nblks != 0) ? (SFS_BLKSIZE - blkoff) : (endpos - offset) * (2) Rd/Wr aligned blocks * NOTICE: useful function: sfs_bmap_load_nolock, sfs_block_op * (3) If end position isn't aligned with the last block, Rd/Wr some content from begin to the (endpos % SFS_BLKSIZE) of the last block * NOTICE: useful function: sfs_bmap_load_nolock, sfs_buf_op */ if ((blkoff = offset % SFS_BLKSIZE) != 0) { size = (nblks != 0) ? (SFS_BLKSIZE - blkoff) : (endpos - offset); if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_buf_op(sfs, buf, size, ino, blkoff)) != 0) { goto out; } alen += size; if (nblks == 0) { goto out; } buf += size, blkno ++, nblks --; } size = SFS_BLKSIZE; while (nblks != 0) { if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_block_op(sfs, buf, ino, 1)) != 0) { goto out; } alen += size, buf += size, blkno ++, nblks --; } if ((size = endpos % SFS_BLKSIZE) != 0) { if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_buf_op(sfs, buf, size, ino, 0)) != 0) { goto out; } alen += size; } out: *alenp = alen; if (offset + alen > sin->din->size) { sin->din->size = offset + alen; sin->dirty = 1; } return ret; }
/* * sfs_io_nolock - Rd/Wr a file contentfrom offset position to offset+ length disk blocks<-->buffer (in memroy) * @sfs: sfs file system * @sin: sfs inode in memory * @buf: the buffer Rd/Wr * @offset: the offset of file * @alenp: the length need to read (is a pointer). and will RETURN the really Rd/Wr lenght * @write: BOOL, 0 read, 1 write */ static int sfs_io_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, void *buf, off_t offset, size_t *alenp, bool write) { struct sfs_disk_inode *din = sin->din; assert(din->type != SFS_TYPE_DIR); off_t endpos = offset + *alenp, blkoff; *alenp = 0; // calculate the Rd/Wr end position if (offset < 0 || offset >= SFS_MAX_FILE_SIZE || offset > endpos) { return -E_INVAL; } if (offset == endpos) { return 0; } if (endpos > SFS_MAX_FILE_SIZE) { endpos = SFS_MAX_FILE_SIZE; } if (!write) { if (offset >= din->size) { return 0; } if (endpos > din->size) { endpos = din->size; } } int (*sfs_buf_op)(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset); int (*sfs_block_op)(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks); if (write) { sfs_buf_op = sfs_wbuf, sfs_block_op = sfs_wblock; } else { sfs_buf_op = sfs_rbuf, sfs_block_op = sfs_rblock; } int ret = 0; size_t size, alen = 0; uint32_t ino; uint32_t blkno = offset / SFS_BLKSIZE; // The NO. of Rd/Wr begin block uint32_t nblks = endpos / SFS_BLKSIZE - blkno; // The size of Rd/Wr blocks //LAB8:EXERCISE1 2012010449 HINT: call sfs_bmap_load_nolock, sfs_rbuf, sfs_rblock,etc. read different kind of blocks in file /* * (1) If offset isn't aligned with the first block, Rd/Wr some content from offset to the end of the first block * NOTICE: useful function: sfs_bmap_load_nolock, sfs_buf_op * Rd/Wr size = (nblks != 0) ? (SFS_BLKSIZE - blkoff) : (endpos - offset) * (2) Rd/Wr aligned blocks * NOTICE: useful function: sfs_bmap_load_nolock, sfs_block_op * (3) If end position isn't aligned with the last block, Rd/Wr some content from begin to the (endpos % SFS_BLKSIZE) of the last block * NOTICE: useful function: sfs_bmap_load_nolock, sfs_buf_op */ //cprintf("Reading from %d to %d, %d blocks\n", offset, endpos, nblks); // Read the first block, if offset is in the middle of the block blkoff = offset % SFS_BLKSIZE; if (blkoff != 0) { size = nblks > 0 ? SFS_BLKSIZE - blkoff : endpos - offset; if (sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) goto out; if (sfs_buf_op(sfs, buf, size, ino, blkoff)) goto out; alen += size; buf = (char *)buf + size; blkno++; } else { // Otherwise read this block either as a full block, or the last block nblks++; } // Read the full blocks int read_count; for (read_count = 0; read_count < (int)nblks - 1; read_count++) { if (sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) goto out; if (sfs_block_op(sfs, buf, ino, 1)) goto out; blkno++; alen += SFS_BLKSIZE; buf = (char *)buf + SFS_BLKSIZE; } // Read the final incomplete block, if it exists size = endpos % SFS_BLKSIZE; if(size != 0 && nblks > 0) { if(sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) goto out; if(sfs_buf_op(sfs, buf, size, ino, 0)) goto out; alen += size; } out: *alenp = alen; if (offset + alen > sin->din->size) { sin->din->size = offset + alen; sin->dirty = 1; } return ret; }
static int sfs_io_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, void *buf, off_t offset, size_t *alenp, bool write) { struct sfs_disk_inode *din = sin->din; assert(_SFS_INODE_GET_TYPE(din) != SFS_TYPE_DIR); off_t endpos = offset + *alenp, blkoff; *alenp = 0; if (offset < 0 || offset >= SFS_MAX_FILE_SIZE || offset > endpos) { return -E_INVAL; } if (offset == endpos) { return 0; } if (endpos > SFS_MAX_FILE_SIZE) { endpos = SFS_MAX_FILE_SIZE; } if (!write) { if (offset >= din->size) { return 0; } if (endpos > din->size) { endpos = din->size; } } int (*sfs_buf_op)(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset); int (*sfs_block_op)(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks); if (write) { sfs_buf_op = sfs_wbuf, sfs_block_op = sfs_wblock; } else { sfs_buf_op = sfs_rbuf, sfs_block_op = sfs_rblock; } int ret = 0; size_t size, alen = 0; uint32_t ino; uint32_t blkno = offset / SFS_BLKSIZE; uint32_t nblks = endpos / SFS_BLKSIZE - blkno; //LAB8:EXERCISE1 2009010989 HINT: call sfs_bmap_load_nolock, sfs_rbuf, sfs_rblock,etc. read different kind of blocks in file if((blkoff = offset % SFS_BLKSIZE)!= 0) { if(nblks){ size = SFS_BLKSIZE - blkoff; }else{ size = endpos - offset; } if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_buf_op(sfs, buf, size, ino, blkoff)) != 0) { goto out; } // add if (write) { // kprintf("write secno %d\n", ino); int secno = ram2block(ino); swapper_block_changed(secno); swapper_block_late_sync(secno); } alen += size; if (nblks == 0) { goto out; } buf += size, blkno ++, nblks --; } size = SFS_BLKSIZE; while(nblks != 0){ if((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if((ret = sfs_block_op(sfs, buf, ino, 1)) != 0) { goto out; } alen += size, buf += size, blkno ++, nblks --; // add if (write) { // kprintf("write secno %d\n", ino); int secno = ram2block(ino); swapper_block_changed(secno); swapper_block_late_sync(secno); } } if((size = endpos % SFS_BLKSIZE) != 0) { if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_buf_op(sfs, buf, size, ino, 0)) != 0) { goto out; } alen += size; // add if (write) { // kprintf("write secno %d\n", ino); int secno = ram2block(ino); swapper_block_changed(secno); swapper_block_late_sync(secno); } } out: *alenp = alen; if (offset + alen > sin->din->size) { sin->din->size = offset + alen; sin->dirty = 1; } return ret; }
static int sfs_io_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, void *buf, off_t offset, size_t *alenp, bool write) { struct sfs_disk_inode *din = sin->din; assert(din->type != SFS_TYPE_DIR); off_t endpos = offset + *alenp, blkoff; *alenp = 0; if (offset < 0 || offset >= SFS_MAX_FILE_SIZE || offset > endpos) { return -E_INVAL; } if (offset == endpos) { return 0; } if (endpos > SFS_MAX_FILE_SIZE) { endpos = SFS_MAX_FILE_SIZE; } if (!write) { if (offset >= din->fileinfo.size) { return 0; } if (endpos > din->fileinfo.size) { endpos = din->fileinfo.size; } } int (*sfs_buf_op)(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset); int (*sfs_block_op)(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks); if (write) { sfs_buf_op = sfs_wbuf, sfs_block_op = sfs_wblock; } else { sfs_buf_op = sfs_rbuf, sfs_block_op = sfs_rblock; } int ret = 0; size_t size, alen = 0; uint32_t ino; uint32_t blkno = offset / SFS_BLKSIZE; uint32_t nblks = endpos / SFS_BLKSIZE - blkno; if ((blkoff = offset % SFS_BLKSIZE) != 0) { size = (nblks != 0) ? (SFS_BLKSIZE - blkoff) : (endpos - offset); if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_buf_op(sfs, buf, size, ino, blkoff)) != 0) { goto out; } alen += size; if (nblks == 0) { goto out; } buf += size, blkno ++, nblks --; } size = SFS_BLKSIZE; while (nblks != 0) { if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_block_op(sfs, buf, ino, 1)) != 0) { goto out; } alen += size, buf += size, blkno ++, nblks --; } if ((size = endpos % SFS_BLKSIZE) != 0) { if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { goto out; } if ((ret = sfs_buf_op(sfs, buf, size, ino, 0)) != 0) { goto out; } alen += size; } out: *alenp = alen; if (offset + alen > din->fileinfo.size) { din->fileinfo.size = offset + alen; sin->dirty = 1; } return ret; }