1/* 2 * linux/fs/hpfs/file.c 3 * 4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999 5 * 6 * file VFS functions 7 */ 8 9#include <linux/string.h> 10#include <linux/sched.h> 11#include <linux/smp_lock.h> 12#include "hpfs_fn.h" 13 14#define BLOCKS(size) (((size) + 511) >> 9) 15 16/* HUH? */ 17int hpfs_open(struct inode *i, struct file *f) 18{ 19 lock_kernel(); 20 hpfs_lock_inode(i); 21 hpfs_unlock_inode(i); /* make sure nobody is deleting the file */ 22 unlock_kernel(); 23 if (!i->i_nlink) return -ENOENT; 24 return 0; 25} 26 27int hpfs_file_release(struct inode *inode, struct file *file) 28{ 29 lock_kernel(); 30 hpfs_write_if_changed(inode); 31 unlock_kernel(); 32 return 0; 33} 34 35int hpfs_file_fsync(struct file *file, struct dentry *dentry, int datasync) 36{ 37 /*return file_fsync(file, dentry);*/ 38 return 0; /* Don't fsync :-) */ 39} 40 41/* 42 * generic_file_read often calls bmap with non-existing sector, 43 * so we must ignore such errors. 44 */ 45 46secno hpfs_bmap(struct inode *inode, unsigned file_secno) 47{ 48 unsigned n, disk_secno; 49 struct fnode *fnode; 50 struct buffer_head *bh; 51 if (BLOCKS(inode->u.hpfs_i.mmu_private) <= file_secno) return 0; 52 n = file_secno - inode->i_hpfs_file_sec; 53 if (n < inode->i_hpfs_n_secs) return inode->i_hpfs_disk_sec + n; 54 if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0; 55 disk_secno = hpfs_bplus_lookup(inode->i_sb, inode, &fnode->btree, file_secno, bh); 56 if (disk_secno == -1) return 0; 57 if (hpfs_chk_sectors(inode->i_sb, disk_secno, 1, "bmap")) return 0; 58 return disk_secno; 59} 60 61void hpfs_truncate(struct inode *i) 62{ 63 if (IS_IMMUTABLE(i)) return /*-EPERM*/; 64 i->i_hpfs_n_secs = 0; 65 i->i_blocks = 1 + ((i->i_size + 511) >> 9); 66 i->u.hpfs_i.mmu_private = i->i_size; 67 hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9)); 68 hpfs_write_inode(i); 69} 70 71int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) 72{ 73 secno s; 74 s = hpfs_bmap(inode, iblock); 75 if (s) { 76 bh_result->b_dev = inode->i_dev; 77 bh_result->b_blocknr = s; 78 bh_result->b_state |= (1UL << BH_Mapped); 79 return 0; 80 } 81 if (!create) return 0; 82 if (iblock<<9 != inode->u.hpfs_i.mmu_private) { 83 BUG(); 84 return -EIO; 85 } 86 if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) { 87 hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); 88 return -ENOSPC; 89 } 90 inode->i_blocks++; 91 inode->u.hpfs_i.mmu_private += 512; 92 bh_result->b_dev = inode->i_dev; 93 bh_result->b_blocknr = s; 94 bh_result->b_state |= (1UL << BH_Mapped) | (1UL << BH_New); 95 return 0; 96} 97 98static int hpfs_writepage(struct page *page) 99{ 100 return block_write_full_page(page,hpfs_get_block); 101} 102static int hpfs_readpage(struct file *file, struct page *page) 103{ 104 return block_read_full_page(page,hpfs_get_block); 105} 106static int hpfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) 107{ 108 return cont_prepare_write(page,from,to,hpfs_get_block, 109 &page->mapping->host->u.hpfs_i.mmu_private); 110} 111static int _hpfs_bmap(struct address_space *mapping, long block) 112{ 113 return generic_block_bmap(mapping,block,hpfs_get_block); 114} 115struct address_space_operations hpfs_aops = { 116 readpage: hpfs_readpage, 117 writepage: hpfs_writepage, 118 sync_page: block_sync_page, 119 prepare_write: hpfs_prepare_write, 120 commit_write: generic_commit_write, 121 bmap: _hpfs_bmap 122}; 123 124ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) 125{ 126 ssize_t retval; 127 128 retval = generic_file_write(file, buf, count, ppos); 129 if (retval > 0) { 130 struct inode *inode = file->f_dentry->d_inode; 131 inode->i_mtime = CURRENT_TIME; 132 inode->i_hpfs_dirty = 1; 133 } 134 return retval; 135} 136 137