patch-2.3.9 linux/fs/hpfs/file.c
Next file: linux/fs/hpfs/hpfs_fn.h
Previous file: linux/fs/hpfs/ea.c
Back to the patch index
Back to the overall index
- Lines: 229
- Date:
Sun Jun 27 10:10:41 1999
- Orig file:
v2.3.8/linux/fs/hpfs/file.c
- Orig date:
Tue Jun 1 23:25:47 1999
diff -u --recursive --new-file v2.3.8/linux/fs/hpfs/file.c linux/fs/hpfs/file.c
@@ -53,143 +53,101 @@
{
if (IS_IMMUTABLE(i)) return /*-EPERM*/;
i->i_hpfs_n_secs = 0;
- hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
i->i_blocks = 1 + ((i->i_size + 511) >> 9);
+ hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
hpfs_write_inode(i);
}
-ssize_t hpfs_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+int hpfs_getblk_block(struct inode *inode, long block, int create, int *err, int *created)
{
- struct inode *inode = filp->f_dentry->d_inode;
- int i,j;
- int a = generic_file_read(filp, buf, count, ppos);
- if (inode->i_hpfs_conv != CONV_TEXT || a < 0) {
- return a;
- }
- for (i = 0, j = 0; i < a; i++) {
- char c;
- int error;
- if ((error = get_user(c, buf + i))) return error;
- if (c != '\r') {
- if (i != j) put_user(c, buf + j);
- j++;
+ 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);
+ 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;
}
- return j;
+ if (!create) {
+ if (err) *err = -EFBIG;
+ up(&inode->i_sem);
+ return 0;
+ }
+ 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++;
+ }
+ inode->i_blocks = add + 1;
+ up(&inode->i_sem);
+ return sec;
}
-ssize_t hpfs_file_write(struct file *filp, const char *buf, size_t count,
- loff_t *ppos)
+/* copied from ext2fs */
+static int hpfs_get_block(struct inode *inode, unsigned long block, struct buffer_head *bh, int update)
{
- struct inode *i = filp->f_dentry->d_inode;
- int carry, error = 0;
- const char *start = buf;
- if (!i) return -EINVAL;
- if (!S_ISREG(i->i_mode)) return -EINVAL;
- if (IS_IMMUTABLE(i)) return -EPERM;
- if (filp->f_flags & O_APPEND) *ppos = i->i_size;
- if (count <= 0) return 0;
- if ((unsigned)(*ppos+count) >= 0x80000000U || (unsigned)count >= 0x80000000U) return -EFBIG;
- carry = 0;
- while (count || carry) {
- int ii, add = 0;
- secno sec = 0; /* Go away, uninitialized variable warning */
- int offset, size, written;
- char ch;
- struct buffer_head *bh;
- char *data;
- offset = *ppos & 0x1ff;
- size = count > 0x200 - offset ? 0x200 - offset : count;
- if ((*ppos >> 9) < ((i->i_size + 0x1ff) >> 9)) {
- i->i_hpfs_n_secs = 0;
- if (!(sec = hpfs_bmap(i, *ppos >> 9))) {
- hpfs_error(i->i_sb, "bmap failed, file %08x, fsec %08x",
- i->i_ino, *ppos >> 9);
- error =- EFSERROR;
- break;
- }
- } else for (ii = (i->i_size + 0x1ff) >> 9, add = 1; ii <= *ppos >> 9; ii++) {
- if ((sec = hpfs_add_sector_to_btree(i->i_sb, i->i_ino, 1, ii)) == -1) {
- hpfs_truncate(i);
- return -ENOSPC;
- }
- if (*ppos != i->i_size)
- if ((data = hpfs_get_sector(i->i_sb, sec, &bh))) {
- memset(data, 0, 512);
- mark_buffer_dirty(bh, 0);
- brelse(bh);
- }
- i->i_size = 0x200 * ii + 1;
- i->i_blocks++;
- /*mark_inode_dirty(i);*/i->i_hpfs_dirty = 1;
- if (i->i_sb->s_hpfs_chk >= 2) {
- secno bsec;
- bsec = hpfs_bmap(i, ii);
- if (sec != bsec) {
- hpfs_error(i->i_sb, "sec == %08x, bmap returns %08x", sec, bsec);
- error = -EFSERROR;
- break;
- }
- }
- PRINTK(("file_write: added %08x\n", sec));
- }
- if (!sec || sec == 15) {
- hpfs_error(i->i_sb, "bmap returned empty sector");
- error = -EFSERROR;
- break;
- }
- if (i->i_sb->s_hpfs_chk)
- if (hpfs_chk_sectors(i->i_sb, sec, 1, "data")) {
- error = -EFSERROR;
- break;
- }
- if ((!offset && size == 0x200) || add)
- data = hpfs_get_sector(i->i_sb, sec, &bh);
- else data = hpfs_map_sector(i->i_sb, sec, &bh, 0);
- if (!data) {
- error = -EIO;
- break;
- }
- if (i->i_hpfs_conv != CONV_TEXT) {
- memcpy_fromfs(data + offset, buf, written = size);
- buf += size;
- } else {
- int left;
- char *to;
- /* LF->CR/LF conversion, stolen from fat fs */
- written = left = 0x200 - offset;
- to = (char *) bh->b_data + (*ppos & 0x1ff);
- if (carry) {
- *to++ = '\n';
- left--;
- carry = 0;
- }
- for (size = 0; size < count && left; size++) {
- if ((error = get_user(ch, buf++))) break;
- if (ch == '\n') {
- *to++ = '\r';
- left--;
- }
- if (!left) carry = 1;
- else {
- *to++ = ch;
- left--;
- }
- }
- written -= left;
+ 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;
}
- update_vm_cache(i, *ppos, bh->b_data + (*ppos & 0x1ff), written);
- *ppos += written;
- if (*ppos > i->i_size) {
- i->i_size = *ppos;
- /*mark_inode_dirty(i);*/i->i_hpfs_dirty = 1;
+
+ 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;
}
- mark_buffer_dirty(bh, 0);
- brelse(bh);
- count -= size;
- }
- if (start == buf) return error;
- i->i_mtime = CURRENT_TIME;
- /*mark_inode_dirty(i);*/i->i_hpfs_dirty = 1;
- return buf - start;
+ }
+
+ if (!update)
+ return 0;
+
+ lock_kernel();
+ ll_rw_block(READ, 1, &bh);
+ wait_on_buffer(bh);
+ unlock_kernel();
+
+ return buffer_uptodate(bh) ? 0 : -EIO;
}
+
+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);
+ if (retval > 0) {
+ struct inode *inode = file->f_dentry->d_inode;
+ inode->i_mtime = CURRENT_TIME;
+ inode->i_hpfs_dirty = 1;
+ }
+ return retval;
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)