diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
commit | 546db14ee74118296f425f3b91634fb767d67290 (patch) | |
tree | 22b613a3da8d4bf663eec5e155af01b87fdf9094 /fs/hpfs | |
parent | 1e25e41c4f5474e14452094492dbc169b800e4c8 (diff) |
Merge with Linux 2.3.23. The new bootmem stuff has broken various
platforms. At this time I've only verified that IP22 support compiles
and IP27 actually works.
Diffstat (limited to 'fs/hpfs')
-rw-r--r-- | fs/hpfs/anode.c | 2 | ||||
-rw-r--r-- | fs/hpfs/dir.c | 41 | ||||
-rw-r--r-- | fs/hpfs/dnode.c | 4 | ||||
-rw-r--r-- | fs/hpfs/file.c | 139 | ||||
-rw-r--r-- | fs/hpfs/hpfs_fn.h | 6 | ||||
-rw-r--r-- | fs/hpfs/inode.c | 8 |
6 files changed, 115 insertions, 85 deletions
diff --git a/fs/hpfs/anode.c b/fs/hpfs/anode.c index 62410ca26..6fb9c1633 100644 --- a/fs/hpfs/anode.c +++ b/fs/hpfs/anode.c @@ -293,10 +293,10 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree) if (!level) return; if (s->s_hpfs_chk) if (hpfs_stop_cycles(s, ano, &c1, &c2, "hpfs_remove_btree #2")) return; + brelse(bh); hpfs_free_sectors(s, ano, 1); oano = ano; ano = anode->up; - brelse(bh); if (--level) { anode = hpfs_map_anode(s, ano, &bh); btree1 = &anode->btree; diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 8af35847d..36e665c32 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -20,7 +20,34 @@ int hpfs_dir_release(struct inode *inode, struct file *filp) return 0; } -int hpfs_readdir(struct file *filp, void * dirent, filldir_t filldir) +/* This is slow, but it's not used often */ + +loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence) +{ + loff_t new_off = off + (whence == 1 ? filp->f_pos : 0); + loff_t pos; + struct quad_buffer_head qbh; + struct inode *i = filp->f_dentry->d_inode; + struct super_block *s = filp->f_dentry->d_sb; + /*printk("dir lseek\n");*/ + if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok; + hpfs_lock_inode(i); + pos = ((loff_t) hpfs_de_as_down_as_possible(s, i->i_hpfs_dno) << 4) + 1; + while (pos != new_off) { + if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh); + else goto fail; + if (pos == 12) goto fail; + } + hpfs_unlock_inode(i); + ok: + return filp->f_pos = new_off; + fail: + hpfs_unlock_inode(i); + /*printk("illegal lseek: %016llx\n", new_off);*/ + return -ESPIPE; +} + +int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; struct quad_buffer_head qbh; @@ -54,11 +81,11 @@ int hpfs_readdir(struct file *filp, void * dirent, filldir_t filldir) if (e) return -EFSERROR; } lc = inode->i_sb->s_hpfs_lowercase; - if (filp->f_pos == -2) { /* diff -r requires this (note, that diff -r */ - filp->f_pos = -3; /* also fails on msdos filesystem in 2.0) */ + if (filp->f_pos == 12) { /* diff -r requires this (note, that diff -r */ + filp->f_pos = 13; /* also fails on msdos filesystem in 2.0) */ return 0; } - if (filp->f_pos == -3) return -ENOENT; + if (filp->f_pos == 13) return -ENOENT; hpfs_lock_inode(inode); @@ -72,7 +99,7 @@ int hpfs_readdir(struct file *filp, void * dirent, filldir_t filldir) hpfs_unlock_inode(inode); return -EFSERROR; } - if (filp->f_pos == -2) { + if (filp->f_pos == 12) { hpfs_unlock_inode(inode); return 0; } @@ -86,9 +113,9 @@ int hpfs_readdir(struct file *filp, void * dirent, filldir_t filldir) hpfs_unlock_inode(inode); return 0; } - filp->f_pos = -1; + filp->f_pos = 11; } - if (filp->f_pos == -1) { + if (filp->f_pos == 11) { if (filldir(dirent, "..", 2, filp->f_pos, inode->i_hpfs_parent_dir) < 0) { hpfs_unlock_inode(inode); return 0; diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index e4b4bbc91..d1ca8e3e6 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c @@ -539,7 +539,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) brelse(bh); } i->i_hpfs_dno = down; - for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, (loff_t) -2); + for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, (loff_t) 12); return; } if (!(dnode = hpfs_map_dnode(i->i_sb, up, &qbh))) return; @@ -876,7 +876,7 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp, hpfs_brelse4(&qbh0); bail: - *posp = -2; + *posp = 12; return de; } diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index fbb1f2f6c..066ce5c28 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -58,91 +58,96 @@ void hpfs_truncate(struct inode *i) hpfs_write_inode(i); } -int hpfs_getblk_block(struct inode *inode, long block, int create, int *err, int *created) +int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) { - int add; - int sec = 0; - down(&inode->i_sem); - if (err) *err = 0; - if (created) *created = 0; - if (!inode->i_blocks) { - hpfs_error(inode->i_sb, "hpfs_get_block: inode %08x has no blocks", inode->i_ino); - if (err) *err = -EFSERROR; - up(&inode->i_sem); + secno s; + if (iblock < inode->i_blocks - 1) { + s = hpfs_bmap(inode, iblock); + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = s; + bh_result->b_state |= (1UL << BH_Mapped); return 0; } - if (block < ((add = inode->i_blocks - 1))) { - int bm; - if (!(bm = hpfs_bmap(inode, block))) { - hpfs_error(inode->i_sb, "hpfs_get_block: cound not bmap block %08x, inode %08x, size %08x", (int)block, inode->i_ino, (int)inode->i_size); - *err = -EFSERROR; - } - up(&inode->i_sem); - return bm; - } - if (!create) { - if (err) *err = -EFBIG; - up(&inode->i_sem); - return 0; + if (!create) return 0; + if (iblock > inode->i_blocks - 1) { + //hpfs_error(inode->i_sb, "hpfs_get_block beyond file end (requested %08x, inode size %08x", (int)iblock, (int)inode->i_blocks - 1); + printk("HPFS: could not write beyond file end. This is known bug.\n"); + return -EFSERROR; } - if (created) *created = 1; - while (add <= block) { - if ((sec = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, add)) == -1) { - if (err) *err = -ENOSPC; - hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); - return 0; - } /* FIXME: clear block */ - add++; + if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) { + hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); + return -ENOSPC; } - inode->i_blocks = add + 1; - up(&inode->i_sem); - return sec; + inode->i_blocks++; + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = s; + bh_result->b_state |= (1UL << BH_Mapped) | (1UL << BH_New); + return 0; } -/* copied from ext2fs */ -static int hpfs_get_block(struct inode *inode, unsigned long block, struct buffer_head *bh, int update) +static int hpfs_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) { - if (!bh->b_blocknr) { - int error, created; - unsigned long blocknr; - - blocknr = hpfs_getblk_block(inode, block, 1, &error, &created); - if (!blocknr) { - if (!error) - error = -ENOSPC; - return error; + struct dentry *dentry = file->f_dentry; + struct inode *inode = dentry->d_inode; + struct page *new_page, **hash; + unsigned long pgpos; + unsigned long page_cache = 0; + long status; + + printk("- off: %08x\n", (int)page->offset); + pgpos = (inode->i_blocks - 1) * 512 & PAGE_CACHE_MASK; + while (pgpos < page->offset) { +long pgp = pgpos; + printk("pgpos: %08x, bl: %d\n", (int)pgpos, (int)inode->i_blocks); + hash = page_hash(inode, pgpos); +repeat_find: new_page = __find_lock_page(inode, pgpos, hash); + if (!new_page) { + if (!page_cache) { + page_cache = page_cache_alloc(); + if (page_cache) + goto repeat_find; + status = -ENOMEM; + goto out; + } + new_page = page_cache_entry(page_cache); + if (add_to_page_cache_unique(new_page,inode,pgpos,hash)) + goto repeat_find; + page_cache = 0; } - - bh->b_dev = inode->i_dev; - bh->b_blocknr = blocknr; - - if (!update) - return 0; - - if (created) { - memset(bh->b_data, 0, bh->b_size); - set_bit(BH_Uptodate, &bh->b_state); - return 0; + printk("A\n"); + status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL); + printk("B\n"); + UnlockPage(new_page); + page_cache_release(new_page); + if (status < 0) + goto out; + pgpos = (inode->i_blocks - 1) * 512 & PAGE_CACHE_MASK; + printk("pgpos2: %08x, bl: %d\n", (int)pgpos, (int)inode->i_blocks); + if (pgpos == pgp) { + status = -1; + printk("ERROR\n"); + goto out; } } - - if (!update) - return 0; - - lock_kernel(); - ll_rw_block(READ, 1, &bh); - wait_on_buffer(bh); - unlock_kernel(); - - return buffer_uptodate(bh) ? 0 : -EIO; + //if ((status = block_write_cont_page(file, page, PAGE_SIZE, 0, NULL)) < 0) goto out; + printk("C\n"); + status = block_write_cont_page(file, page, offset, bytes, buf); + printk("D\n"); +out: + printk("O\n"); + if (page_cache) + page_cache_free(page_cache); + printk("E\n"); + return status; } + ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { ssize_t retval; retval = generic_file_write(file, buf, count, - ppos, block_write_partial_page); + ppos, /*hpfs_write_partial_page*/block_write_partial_page); if (retval > 0) { struct inode *inode = file->f_dentry->d_inode; inode->i_mtime = CURRENT_TIME; diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 050b63597..9ae4a67da 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h @@ -226,6 +226,7 @@ void hpfs_set_dentry_operations(struct dentry *); int hpfs_dir_read(struct file *, char *, size_t, loff_t *); int hpfs_dir_release(struct inode *, struct file *); +loff_t hpfs_dir_lseek(struct file *, loff_t, int); int hpfs_readdir(struct file *, void *, filldir_t); struct dentry *hpfs_lookup(struct inode *, struct dentry *); @@ -258,9 +259,8 @@ int hpfs_open(struct inode *, struct file *); int hpfs_file_fsync(struct file *, struct dentry *); secno hpfs_bmap(struct inode *, unsigned); void hpfs_truncate(struct inode *); -ssize_t hpfs_file_read(struct file *, char *, size_t, loff_t *); -ssize_t hpfs_file_write(struct file *, const char *, size_t, loff_t *); -int hpfs_writepage (struct file *, struct page *); +int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create); +ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos); /* inode.c */ diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index efc776218..d79e55814 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -41,11 +41,9 @@ static const struct inode_operations hpfs_file_iops = NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - (int (*)(struct inode *, int)) -#warning Someone needs to code up hpfs_get_block properly... -DaveM - &hpfs_bmap, /* get_block */ + &hpfs_get_block, /* get_block */ block_read_full_page, /* readpage */ - hpfs_writepage, /* writepage */ + block_write_full_page, /* writepage */ block_flushpage, /* flushpage */ hpfs_truncate, /* truncate */ NULL, /* permission */ @@ -55,7 +53,7 @@ static const struct inode_operations hpfs_file_iops = static const struct file_operations hpfs_dir_ops = { - NULL, /* lseek - default */ + hpfs_dir_lseek, /* lseek */ hpfs_dir_read, /* read */ NULL, /* write - bad */ hpfs_readdir, /* readdir */ |