Messages in this thread Patch in this message | | | Date | Fri, 25 Jun 1999 18:38:20 +0200 (CEST) | From | Mikulas Patocka <> | Subject | hpfs patch |
| |
Hi. Here goes patch for HPFS against 2.3.9-pre3. It seems to work. I won't have access to net during holiday, this is the last patch I'm sending.
Mikulas Patocka Binary files linux-clean/linux/fs/ext2/inode.c.swp and linux/fs/ext2/inode.c.swp differ diff -urN -x *.[aos] -x *.rej -x *.orig -x *.flags -x *.tgz -x *.tar.gz -x *.map -x vmlinu* -x zImage -x .* -x bootsect -x setup -x build -x compile.h -x consolemap_deftbl.c -x conmakehash -x mkinst -x mk -x mkdist -x mnt -x hpfs-ro -x asm -x config -x autoconf.h -x version.h -x modversions.h -x modules -x scripts linux-clean/linux/fs/hpfs/Makefile linux/fs/hpfs/Makefile --- linux-clean/linux/fs/hpfs/Makefile Sat May 15 20:32:50 1999 +++ linux/fs/hpfs/Makefile Fri Jun 25 18:09:29 1999 @@ -1,5 +1,5 @@ O_TARGET := hpfs.o -O_OBJS := alloc.o anode.o buffer.o dentry.o dir.o dnode.o ea.o file.o inode.o map.o mmap.o name.o namei.o super.o +O_OBJS := alloc.o anode.o buffer.o dentry.o dir.o dnode.o ea.o file.o inode.o map.o name.o namei.o super.o M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff -urN -x *.[aos] -x *.rej -x *.orig -x *.flags -x *.tgz -x *.tar.gz -x *.map -x vmlinu* -x zImage -x .* -x bootsect -x setup -x build -x compile.h -x consolemap_deftbl.c -x conmakehash -x mkinst -x mk -x mkdist -x mnt -x hpfs-ro -x asm -x config -x autoconf.h -x version.h -x modversions.h -x modules -x scripts linux-clean/linux/fs/hpfs/file.c linux/fs/hpfs/file.c --- linux-clean/linux/fs/hpfs/file.c Wed Jun 23 11:28:15 1999 +++ linux/fs/hpfs/file.c Fri Jun 25 14:40:32 1999 @@ -53,143 +53,111 @@ { 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; + } + if (!create) { + if (err) *err = -EFBIG; + up(&inode->i_sem); + return 0; } - return j; + 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; +} + +int hpfs_writepage(struct file *file, struct page *page) +{ + return block_write_full_page(file, page, hpfs_get_block); +} + +long hpfs_write_one_page (struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char *buf) +{ + return block_write_partial_page(file, page, offset, bytes, buf, hpfs_get_block); } + + +ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + ssize_t retval; + struct inode *inode = file->f_dentry->d_inode; + retval = generic_file_write(file, buf, count, ppos, hpfs_write_one_page); + if (retval > 0) { + /*remove_suid(inode);*/ + inode->i_mtime = CURRENT_TIME; + inode->i_hpfs_dirty = 1; + } + return retval; +} + diff -urN -x *.[aos] -x *.rej -x *.orig -x *.flags -x *.tgz -x *.tar.gz -x *.map -x vmlinu* -x zImage -x .* -x bootsect -x setup -x build -x compile.h -x consolemap_deftbl.c -x conmakehash -x mkinst -x mk -x mkdist -x mnt -x hpfs-ro -x asm -x config -x autoconf.h -x version.h -x modversions.h -x modules -x scripts linux-clean/linux/fs/hpfs/hpfs_fn.h linux/fs/hpfs/hpfs_fn.h --- linux-clean/linux/fs/hpfs/hpfs_fn.h Wed Jun 2 20:19:44 1999 +++ linux/fs/hpfs/hpfs_fn.h Fri Jun 25 14:43:42 1999 @@ -21,6 +21,7 @@ #include <asm/bitops.h> #include <asm/segment.h> #include <asm/uaccess.h> +#include <linux/smp_lock.h> #include <stdarg.h> @@ -259,6 +260,7 @@ 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 *); /* inode.c */ diff -urN -x *.[aos] -x *.rej -x *.orig -x *.flags -x *.tgz -x *.tar.gz -x *.map -x vmlinu* -x zImage -x .* -x bootsect -x setup -x build -x compile.h -x consolemap_deftbl.c -x conmakehash -x mkinst -x mk -x mkdist -x mnt -x hpfs-ro -x asm -x config -x autoconf.h -x version.h -x modversions.h -x modules -x scripts linux-clean/linux/fs/hpfs/inode.c linux/fs/hpfs/inode.c --- linux-clean/linux/fs/hpfs/inode.c Fri Jun 25 14:05:56 1999 +++ linux/fs/hpfs/inode.c Fri Jun 25 14:05:16 1999 @@ -11,7 +11,7 @@ static const struct file_operations hpfs_file_ops = { NULL, /* lseek - default */ - hpfs_file_read, /* read */ + generic_file_read, /* read */ hpfs_file_write, /* write */ NULL, /* readdir - bad */ NULL, /* poll - default */ @@ -44,9 +44,9 @@ (int (*)(struct inode *, int)) &hpfs_bmap, /* bmap */ block_read_full_page, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - &hpfs_truncate, /* truncate */ + hpfs_writepage, /* writepage */ + block_flushpage, /* flushpage */ + hpfs_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ NULL, /* revalidate */ @@ -92,7 +92,7 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL, /* revalidate */ + NULL /* revalidate */ }; const struct inode_operations hpfs_symlink_iops = @@ -116,7 +116,7 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL, /* revalidate */ + NULL /* revalidate */ }; @@ -128,7 +128,6 @@ unsigned char *ea; int ea_size; i->i_op = 0; - /*i->i_hpfs_sem = MUTEX;*/ init_MUTEX(&i->i_hpfs_sem); i->i_uid = sb->s_hpfs_uid; i->i_gid = sb->s_hpfs_gid; diff -urN -x *.[aos] -x *.rej -x *.orig -x *.flags -x *.tgz -x *.tar.gz -x *.map -x vmlinu* -x zImage -x .* -x bootsect -x setup -x build -x compile.h -x consolemap_deftbl.c -x conmakehash -x mkinst -x mk -x mkdist -x mnt -x hpfs-ro -x asm -x config -x autoconf.h -x version.h -x modversions.h -x modules -x scripts linux-clean/linux/fs/hpfs/mmap.c linux/fs/hpfs/mmap.c --- linux-clean/linux/fs/hpfs/mmap.c Sat May 15 20:32:50 1999 +++ linux/fs/hpfs/mmap.c Thu Jan 1 01:00:00 1970 @@ -1,128 +0,0 @@ -/* - * linux/fs/hpfs/mmap.c - * - * taken from fat filesystem - * - * Written by Jacques Gelinas (jacques@solucorp.qc.ca) - * Inspired by fs/nfs/mmap.c (Jon Tombs 15 Aug 1993) - * - * Modified for HPFS by Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz) - * - * mmap handling for hpfs filesystem - * (generic_file_mmap may be used only on filesystems that keep zeros - * in last file sector beyond end) - */ - -/* - * generic_file_mmap doesn't erase the space beyond file end in last sector. :-( - * Hpfs doesn't keep zeros in last sector. This causes problems with kernel - * mkdep.c and probably other programs. Additionally this could be a security - * hole - some interesting data, like pieces of /etc/shadow could be found - * beyond file end. - * - * So, I can't use generic mmap. mmap from fat filesystem looks good, so I used - * it. - * - * BTW. fat uses generic mmap on normal disks. Doesn't it also have above bugs? - * I don't think Msdos erases space in last sector. - * - * If you fix generic_file_mmap, you can remove this file and use it. - */ - -#include "hpfs_fn.h" - -/* - * Fill in the supplied page for mmap - */ - -static unsigned long hpfs_file_mmap_nopage( - struct vm_area_struct * area, - unsigned long address, - int error_code) -{ - /*struct inode * inode = area->vm_inode;*/ - struct inode * inode = area->vm_file->f_dentry->d_inode; - unsigned long page; - unsigned int clear; - loff_t pos; - long gap; /* distance from eof to pos */ - - page = __get_free_page(GFP_KERNEL); - if (!page) - return page; - address &= PAGE_MASK; - pos = address - area->vm_start + area->vm_offset; - - clear = 0; - gap = inode->i_size - pos; - if (gap <= 0){ - /* mmaping beyond end of file */ - clear = PAGE_SIZE; - }else{ - int cur_read; - int need_read; - /*struct file *filp = area->vm_file;*/ - struct file filp; - if (gap < PAGE_SIZE){ - clear = PAGE_SIZE - gap; - } - filp.f_reada = 0; - filp.f_pos = pos; - filp.f_dentry=area->vm_file->f_dentry; - need_read = PAGE_SIZE - clear; - { - mm_segment_t cur_fs = get_fs(); - set_fs (KERNEL_DS); - cur_read = generic_file_read (&filp,(char*)page - ,need_read,&pos); - set_fs (cur_fs); - } - if (cur_read != need_read){ - hpfs_error(inode->i_sb, "Error while reading an mmap file %08x", inode->i_ino); - } - } - if (clear > 0){ - memset ((char*)page+PAGE_SIZE-clear,0,clear); - } - return page; -} - -struct vm_operations_struct hpfs_file_mmap = { - NULL, /* open */ - NULL, /* close */ - NULL, /* unmap */ - NULL, /* protect */ - NULL, /* sync */ - NULL, /* advise */ - hpfs_file_mmap_nopage, /* nopage */ - NULL, /* wppage */ - NULL, /* swapout */ - NULL, /* swapin */ -}; - -/* - * This is used for a general mmap of an msdos file - * Returns 0 if ok, or a negative error code if not. - */ -int hpfs_mmap(struct file * file, struct vm_area_struct * vma) -{ - struct inode *inode = file->f_dentry->d_inode; - /*printk("start mmap\n");*/ - if (vma->vm_flags & VM_SHARED) /* only PAGE_COW or read-only supported now */ - return -EINVAL; - if (vma->vm_offset & (inode->i_sb->s_blocksize - 1)) - return -EINVAL; - if (!inode->i_sb || !S_ISREG(inode->i_mode)) - return -EACCES; - /*if (!IS_RDONLY(inode)) { - inode->i_atime = CURRENT_TIME; - mark_inode_dirty(inode); - }*/ - - vma->vm_file = file; - /*inode->i_count++;*/ - file->f_count++; - vma->vm_ops = &hpfs_file_mmap; - /*printk("end mmap\n");*/ - return 0; -} | |