summaryrefslogtreecommitdiffstats
path: root/fs/hpfs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-27 01:05:20 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-27 01:05:20 +0000
commit546db14ee74118296f425f3b91634fb767d67290 (patch)
tree22b613a3da8d4bf663eec5e155af01b87fdf9094 /fs/hpfs
parent1e25e41c4f5474e14452094492dbc169b800e4c8 (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.c2
-rw-r--r--fs/hpfs/dir.c41
-rw-r--r--fs/hpfs/dnode.c4
-rw-r--r--fs/hpfs/file.c139
-rw-r--r--fs/hpfs/hpfs_fn.h6
-rw-r--r--fs/hpfs/inode.c8
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 */