]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.9pre4 2.3.9pre4
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:25:49 +0000 (15:25 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:25:49 +0000 (15:25 -0500)
15 files changed:
arch/i386/defconfig
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/mm/init.c
drivers/block/ll_rw_blk.c
drivers/block/raid5.c
drivers/block/rd.c
fs/buffer.c
fs/ext2/file.c
fs/ext2/inode.c
fs/hpfs/Makefile
fs/hpfs/file.c
fs/hpfs/hpfs_fn.h
fs/hpfs/inode.c
fs/hpfs/mmap.c [deleted file]
include/linux/fs.h

index b5ede650874a45970b64a00494c4e53d421e897f..856ceecf3a7f1cb21dbbcdff3250960de0adfd9c 100644 (file)
@@ -314,17 +314,7 @@ CONFIG_82C710_MOUSE=y
 #
 # USB drivers - not for the faint of heart
 #
-CONFIG_USB=y
-CONFIG_USB_UHCI=y
-# CONFIG_USB_OHCI is not set
-# CONFIG_USB_OHCI_HCD is not set
-CONFIG_USB_HUB=y
-CONFIG_USB_MOUSE=y
-CONFIG_USB_KBD=y
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SCSI is not set
+# CONFIG_USB is not set
 
 #
 # Filesystems
index a4d6c7116bde93cc82696bd0cc1589e1c06ea8cb..a680814ebe604dae3e90e0d40e3bdc65bec9e542 100644 (file)
@@ -2834,7 +2834,6 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
        bprm.dentry = dentry;
        bprm.filename = filename;
        bprm.sh_bang = 0;
-       bprm.java = 0;
        bprm.loader = 0;
        bprm.exec = 0;
        if ((bprm.argc = count32(argv)) < 0) {
index 6f3232d1d4c6394a250247030df478648d835b75..c7eeb066da6d24730a8e2cf21c8af76bf58ed3ef 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.128 1999/05/25 16:53:24 jj Exp $
+/*  $Id: init.c,v 1.129 1999/06/25 10:32:08 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -419,10 +419,12 @@ __u32 mmu_get_scsi_one(char *vaddr, unsigned long len, struct linux_sbus *sbus)
        }
 
        if (iommu->strbuf_enabled) {
+               volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
+
                spin_lock_irqsave(&iommu->iommu_lock, flags);
                iommu->flushflag = 0;
                while(start < end) {
-                       sregs->sbuf_pflush = start;
+                       *sbuf_pflush = start;
                        start += PAGE_SIZE;
                }
                sregs->sbuf_fsync = __pa(&(iommu->flushflag));
@@ -447,6 +449,8 @@ void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus)
        start &= PAGE_MASK;
 
        if (iommu->strbuf_enabled) {
+               volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
+
                spin_lock_irqsave(&iommu->iommu_lock, flags);
 
                /* 1) Clear the flush flag word */
@@ -456,7 +460,7 @@ void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus)
                 *    we want flushed.
                 */
                while(start < end) {
-                       sregs->sbuf_pflush = start;
+                       *sbuf_pflush = start;
                        start += PAGE_SIZE;
                }
 
@@ -484,6 +488,8 @@ void mmu_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
        volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
 
        if (iommu->strbuf_enabled) {
+               volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
+
                spin_lock_irqsave(&iommu->iommu_lock, flags);
                iommu->flushflag = 0;
 
@@ -500,7 +506,7 @@ void mmu_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
                        sg[sz--].dvma_addr = sbus_dvma_addr(start);
                        start &= PAGE_MASK;
                        while(start < end) {
-                               sregs->sbuf_pflush = start;
+                               *sbuf_pflush = start;
                                start += PAGE_SIZE;
                        }
                }
@@ -535,6 +541,8 @@ void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus
        unsigned long flags, tmp;
 
        if (iommu->strbuf_enabled) {
+               volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
+
                spin_lock_irqsave(&iommu->iommu_lock, flags);
 
                /* 1) Clear the flush flag word */
@@ -549,7 +557,7 @@ void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus
 
                        start &= PAGE_MASK;
                        while(start < end) {
-                               sregs->sbuf_pflush = start;
+                               *sbuf_pflush = start;
                                start += PAGE_SIZE;
                        }
                        sz--;
index 39f0aeadd353b427fb2321e74d51ff582928dbb3..851d6f59803912c0409dbd7ad544fbd8515fc947 100644 (file)
@@ -384,12 +384,9 @@ void make_request(int major,int rw, struct buffer_head * bh)
        count = bh->b_size >> 9;
        sector = bh->b_rsector;
 
-       /* Uhhuh.. Nasty dead-lock possible here.. */
-       if (buffer_locked(bh))
+       /* Only one thread can actually submit the I/O. */
+       if (test_and_set_bit(BH_Lock, &bh->b_state))
                return;
-       /* Maybe the above fixes it, and maybe it doesn't boot. Life is interesting */
-
-       lock_buffer(bh);
 
        if (blk_size[major]) {
                unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
index 3c5701b3eae719f7156a4ec2cbb652d0d6f9935e..609cdaaf59b231308404eb05c9b10363937db980 100644 (file)
@@ -586,13 +586,15 @@ static void raid5_build_block (struct stripe_head *sh, struct buffer_head *bh, i
 
        b_data = ((volatile struct buffer_head *) bh)->b_data;
        memset (bh, 0, sizeof (struct buffer_head));
-       init_buffer(bh, dev, block, raid5_end_request, sh);
+       init_buffer(bh, raid5_end_request, sh);
+       bh->b_dev = dev;
+       bh->b_blocknr = block;
        ((volatile struct buffer_head *) bh)->b_data = b_data;
 
        bh->b_rdev      = raid_conf->disks[i].dev;
        bh->b_rsector   = sh->sector;
 
-       bh->b_state     = (1 << BH_Req);
+       bh->b_state     = (1 << BH_Req) | (1 << BH_Allocated);
        bh->b_size      = sh->size;
        bh->b_list      = BUF_LOCKED;
 }
index 81ce11c49bb26eb5785278fdbe97bda38fa41faa..6c2768b279455adf4f9c7e91d474634cdae1971d 100644 (file)
@@ -173,7 +173,7 @@ repeat:
 
        if (CURRENT->cmd == READ) 
                memset(CURRENT->buffer, 0, len); 
-       else    
+       else
                set_bit(BH_Protected, &CURRENT->bh->b_state);
 
        end_request(1);
index 5823ddeb034fbd4c478d3e03f79baf0e7aedf7b9..9c0a66db7bf83e2d9d7c341914b0231fef8c657a 100644 (file)
@@ -71,7 +71,6 @@ static struct buffer_head * free_list[NR_SIZES] = {NULL, };
 static kmem_cache_t *bh_cachep;
 
 static struct buffer_head * unused_list = NULL;
-static struct buffer_head * reuse_list = NULL;
 static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
 
 static int nr_buffers = 0;
@@ -671,13 +670,10 @@ static void refill_freelist(int size)
        }
 }
 
-void init_buffer(struct buffer_head *bh, kdev_t dev, int block,
-                bh_end_io_t *handler, void *dev_id)
+void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *dev_id)
 {
        bh->b_list = BUF_CLEAN;
        bh->b_flushtime = 0;
-       bh->b_dev = dev;
-       bh->b_blocknr = block;
        bh->b_end_io = handler;
        bh->b_dev_id = dev_id;
 }
@@ -725,9 +721,10 @@ static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
         */
        spin_lock_irqsave(&page_uptodate_lock, flags);
        unlock_buffer(bh);
+       bh->b_count--;
        tmp = bh->b_this_page;
        while (tmp != bh) {
-               if (buffer_locked(tmp))
+               if (tmp->b_count && (tmp->b_end_io == end_buffer_io_async))
                        goto still_busy;
                tmp = tmp->b_this_page;
        }
@@ -806,9 +803,11 @@ get_free:
        /* OK, FINALLY we know that this buffer is the only one of its kind,
         * and that it's unused (b_count=0), unlocked, and clean.
         */
-       init_buffer(bh, dev, block, end_buffer_io_sync, NULL);
+       init_buffer(bh, end_buffer_io_sync, NULL);
+       bh->b_dev = dev;
+       bh->b_blocknr = block;
        bh->b_count = 1;
-       bh->b_state = 0;
+       bh->b_state = 1 << BH_Allocated;
 
        /* Insert the buffer into the regular lists */
        insert_into_lru_list(bh);
@@ -1042,35 +1041,6 @@ static void put_unused_buffer_head(struct buffer_head * bh)
        unused_list = bh;
 }
 
-/* 
- * We can't put completed temporary IO buffer_heads directly onto the
- * unused_list when they become unlocked, since the device driver
- * end_request routines still expect access to the buffer_head's
- * fields after the final unlock.  So, the device driver puts them on
- * the reuse_list instead once IO completes, and we recover these to
- * the unused_list here.
- *
- * Note that we don't do a wakeup here, but return a flag indicating
- * whether we got any buffer heads. A task ready to sleep can check
- * the returned value, and any tasks already sleeping will have been
- * awakened when the buffer heads were added to the reuse list.
- */
-static inline int recover_reusable_buffer_heads(void)
-{
-       struct buffer_head *head = xchg(&reuse_list, NULL);
-       int found = 0;
-       
-       if (head) {
-               do {
-                       struct buffer_head *bh = head;
-                       head = head->b_next_free;
-                       put_unused_buffer_head(bh);
-               } while (head);
-               found = 1;
-       }
-       return found;
-}
-
 /*
  * Reserve NR_RESERVED buffer heads for async IO requests to avoid
  * no-buffer-head deadlock.  Return NULL on failure; waiting for
@@ -1080,7 +1050,6 @@ static struct buffer_head * get_unused_buffer_head(int async)
 {
        struct buffer_head * bh;
 
-       recover_reusable_buffer_heads();
        if (nr_unused_buffer_heads > NR_RESERVED) {
                bh = unused_list;
                unused_list = bh->b_next_free;
@@ -1204,8 +1173,10 @@ no_grow:
         */
        add_wait_queue(&buffer_wait, &wait);
        current->state = TASK_UNINTERRUPTIBLE;
-       if (!recover_reusable_buffer_heads())
+       if (nr_unused_buffer_heads < MAX_BUF_PER_PAGE) {
+               current->policy |= SCHED_YIELD;
                schedule();
+       }
        remove_wait_queue(&buffer_wait, &wait);
        current->state = TASK_RUNNING;
        goto try_again;
@@ -1237,7 +1208,9 @@ static int create_page_buffers(int rw, struct page *page, kdev_t dev, int b[], i
                block = *(b++);
 
                tail = bh;
-               init_buffer(bh, dev, block, end_buffer_io_async, NULL);
+               init_buffer(bh, end_buffer_io_async, NULL);
+               bh->b_dev = dev;
+               bh->b_blocknr = block;
 
                /*
                 * When we use bmap, we define block zero to represent
@@ -1247,7 +1220,10 @@ static int create_page_buffers(int rw, struct page *page, kdev_t dev, int b[], i
                 */
                if (bmap && !block) {
                        memset(bh->b_data, 0, size);
+                       set_bit(BH_Uptodate, &bh->b_state);
+                       continue;
                }
+               set_bit(BH_Allocated, &bh->b_state);
        }
        tail->b_this_page = head;
        get_page(page);
@@ -1283,13 +1259,14 @@ int block_flushpage(struct inode *inode, struct page *page, unsigned long offset
                 * is this block fully flushed?
                 */
                if (offset <= curr_off) {
-                       if (bh->b_blocknr) {
+                       if (buffer_allocated(bh)) {
                                bh->b_count++;
                                wait_on_buffer(bh);
                                if (bh->b_dev == B_FREE)
                                        BUG();
                                mark_buffer_clean(bh);
                                clear_bit(BH_Uptodate, &bh->b_state);
+                               clear_bit(BH_Allocated, &bh->b_state);
                                bh->b_blocknr = 0;
                                bh->b_count--;
                        }
@@ -1381,8 +1358,8 @@ int block_write_full_page (struct file *file, struct page *page, fs_getblock_t f
                 * decisions (block #0 may actually be a valid block)
                 */
                bh->b_end_io = end_buffer_io_sync;
-               if (!buffer_uptodate(bh)) {
-                       err = fs_get_block(inode, block, bh, 0);
+               if (!buffer_allocated(bh)) {
+                       err = fs_get_block(inode, block, bh, FS_GETBLK_ALLOCATE);
                        if (err)
                                goto out;
                }
@@ -1470,14 +1447,27 @@ int block_write_partial_page (struct file *file, struct page *page, unsigned lon
                 * not going to fill it completely.
                 */
                bh->b_end_io = end_buffer_io_sync;
-               if (!buffer_uptodate(bh)) {
-                       int update = start_offset || (end_bytes && (i == end_block));
-
-                       err = fs_get_block(inode, block, bh, update);
+               if (!buffer_allocated(bh)) {
+                       unsigned int flags = FS_GETBLK_ALLOCATE;
+                       if (start_offset || (end_bytes && (i == end_block)))
+                               flags |= FS_GETBLK_UPDATE;
+                       err = fs_get_block(inode, block, bh, flags);
                        if (err)
                                goto out;
                }
 
+               if (start_offset || (end_bytes && (i == end_block))) {
+                       if (!buffer_uptodate(bh)) {
+                               lock_kernel();
+                               ll_rw_block(READ, 1, &bh);
+                               wait_on_buffer(bh);
+                               unlock_kernel();
+                               err = -EIO;
+                               if (!buffer_uptodate(bh))
+                                       goto out;
+                       }
+               }
+
                err = -EFAULT;
                len = blocksize;
                if (start_offset) {
@@ -1586,6 +1576,7 @@ int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size, int bmap)
                                        BUG();
                                if (!buffer_uptodate(bh)) {
                                        arr[nr++] = bh;
+                                       bh->b_count++;
                                }
                        }
                } else { /* WRITE */
@@ -1600,6 +1591,7 @@ int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size, int bmap)
                        set_bit(BH_Uptodate, &bh->b_state);
                        set_bit(BH_Dirty, &bh->b_state);
                        arr[nr++] = bh;
+                       bh->b_count++;
                }
                bh = bh->b_this_page;
        } while (bh != head);
@@ -1680,23 +1672,30 @@ int block_read_full_page(struct file * file, struct page * page)
                 * their bnr cached but had an IO error!
                 */
                if (!buffer_uptodate(bh)) {
-                       phys_block = inode->i_op->bmap(inode, iblock);
+                       unsigned long phys_block = bh->b_blocknr;
+                       if (!buffer_allocated(bh)) {
+                               phys_block = inode->i_op->bmap(inode, iblock);
+                               if (phys_block) {
+                                       bh->b_dev = inode->i_dev;
+                                       bh->b_blocknr = phys_block;
+                                       set_bit(BH_Allocated, &bh->b_state);
+                               }
+                       }
+                                       
                        /*
                         * this is safe to do because we hold the page lock:
                         */
                        if (phys_block) {
-                               init_buffer(bh, inode->i_dev, phys_block, end_buffer_io_async, NULL);
+                               init_buffer(bh, end_buffer_io_async, NULL);
                                arr[nr] = bh;
+                               bh->b_count++;
                                nr++;
                        } else {
                                /*
                                 * filesystem 'hole' represents zero-contents.
-                                *
-                                * Don't mark the buffer up-to-date (that also implies
-                                * that it is ok on disk, which it isn't), but _do_
-                                * zero out the contents so that readers see the zeroes.
                                 */
                                memset(bh->b_data, 0, blocksize);
+                               set_bit(BH_Uptodate, &bh->b_state);
                        }
                }
                iblock++;
index 02a3c1d97a2718ccb6fe26f32be3b9066899c16c..d78181b2b28a03ba786987550544f382da58ff0b 100644 (file)
@@ -106,41 +106,32 @@ static inline void remove_suid(struct inode *inode)
        }
 }
 
-static int ext2_get_block(struct inode *inode, unsigned long block, struct buffer_head *bh, int update)
+static int ext2_get_block(struct inode *inode, unsigned long block, struct buffer_head *bh, unsigned int flags)
 {
-       if (!bh->b_blocknr) {
-               int error, created;
-               unsigned long blocknr;
-
-               blocknr = ext2_getblk_block(inode, block, 1, &error, &created);
-               if (!blocknr) {
-                       if (!error)
-                               error = -ENOSPC;
-                       return error;
-               }
+       int error, created;
+       unsigned long blocknr;
 
-               bh->b_dev = inode->i_dev;
-               bh->b_blocknr = blocknr;
+       blocknr = ext2_getblk_block(inode, block, flags & FS_GETBLK_ALLOCATE, &error, &created);
+       if (!blocknr) {
+               if (error)
+                       return error;
+               if (!(flags & FS_GETBLK_ALLOCATE))
+                       goto clear_and_uptodate;
+               return -ENOSPC;
+       }
 
-               if (!update)
-                       return 0;
+       bh->b_dev = inode->i_dev;
+       bh->b_blocknr = blocknr;
+       set_bit(BH_Allocated, &bh->b_state);
 
-               if (created) {
+       if (created) {
+clear_and_uptodate:
+               if (flags & FS_GETBLK_UPDATE) {
                        memset(bh->b_data, 0, bh->b_size);
                        set_bit(BH_Uptodate, &bh->b_state);
-                       return 0;
                }
        }
-
-       if (!update)
-               return 0;
-
-       lock_kernel();
-       ll_rw_block(READ, 1, &bh);
-       wait_on_buffer(bh);
-       unlock_kernel();
-
-       return buffer_uptodate(bh) ? 0 : -EIO;
+       return 0;
 }
 
 static int ext2_writepage (struct file * file, struct page * page)
index d808fc3062c9622770797488b044d691c9127169..db80ff3649db4a730744196aab3d17cf54106ea2 100644 (file)
@@ -501,7 +501,7 @@ int ext2_getblk_block (struct inode * inode, long block,
                inode->u.ext2_i.i_next_alloc_goal++;
        }
 
-       *err = 0; // -ENOSPC;
+       *err = 0;
        b = block;
        *created = 0;
        if (block < EXT2_NDIR_BLOCKS) {
index 46f1ffae02b1034f7427b2eccf58062497032090..2ebaece024b69d76d38ad7690339d91ef5c3f26d 100644 (file)
@@ -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
index 7cea8dcdc099c35b5c93e9a0b0da0f4c7fb6cf46..88bd8b88697623c5db911bd105d0db4ec13ec32b 100644 (file)
@@ -53,143 +53,111 @@ void hpfs_truncate(struct inode *i)
 {
        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;
+}
+
index cdb2c709e495a04c11b1595ad590a8b0a2d75a7a..050b63597b17ded7e3710047397dd9867b4cc23a 100644 (file)
@@ -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 @@ 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 *);
 
 /* inode.c */
 
index 111b416d9204cf8f0cad6c91f1360703665a7edf..b3132c450f587d637a98cb8932f7cea1c331b8e5 100644 (file)
@@ -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 @@ static const struct inode_operations hpfs_file_iops =
        (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 @@ static const struct inode_operations hpfs_dir_iops =
        NULL,                           /* truncate */
        NULL,                           /* permission */
        NULL,                           /* smap */
-       NULL,                           /* revalidate */
+       NULL                            /* revalidate */
 };
 
 const struct inode_operations hpfs_symlink_iops =
@@ -116,7 +116,7 @@ const struct inode_operations hpfs_symlink_iops =
        NULL,                           /* truncate */
        NULL,                           /* permission */
        NULL,                           /* smap */
-       NULL,                           /* revalidate */
+       NULL                            /* revalidate */
 };
 
 
@@ -128,7 +128,6 @@ void hpfs_read_inode(struct inode *i)
        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 --git a/fs/hpfs/mmap.c b/fs/hpfs/mmap.c
deleted file mode 100644 (file)
index 3fd5446..0000000
+++ /dev/null
@@ -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;
-}
index 0f664ed041da3dbde3712d332ba1eb280f775f09..89697693ed20a9942e72de3cc086aae64a90697a 100644 (file)
@@ -188,7 +188,9 @@ typedef char buffer_block[BLOCK_SIZE];
 #define BH_Dirty       1       /* 1 if the buffer is dirty */
 #define BH_Lock                2       /* 1 if the buffer is locked */
 #define BH_Req         3       /* 0 if the buffer has been invalidated */
+#define BH_Allocated   4       /* 1 if the buffer has allocated backing store */
 #define BH_Protected   6       /* 1 if the buffer is protected */
+
 /*
  * Try to keep the most commonly used fields in single cache lines (16
  * bytes) to improve performance.  This ordering should be
@@ -232,7 +234,7 @@ struct buffer_head {
 };
 
 typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
-void init_buffer(struct buffer_head *, kdev_t, int, bh_end_io_t *, void *);
+void init_buffer(struct buffer_head *, bh_end_io_t *, void *);
 
 #define __buffer_state(bh, state)      (((bh)->b_state & (1UL << BH_##state)) != 0)
 
@@ -240,6 +242,7 @@ void init_buffer(struct buffer_head *, kdev_t, int, bh_end_io_t *, void *);
 #define buffer_dirty(bh)       __buffer_state(bh,Dirty)
 #define buffer_locked(bh)      __buffer_state(bh,Lock)
 #define buffer_req(bh)         __buffer_state(bh,Req)
+#define buffer_allocated(bh)   __buffer_state(bh,Allocated)
 #define buffer_protected(bh)   __buffer_state(bh,Protected)
 
 #define buffer_page(bh)                (mem_map + MAP_NR((bh)->b_data))
@@ -870,7 +873,10 @@ extern struct buffer_head * breada(kdev_t, int, int, unsigned int, unsigned int)
 extern int brw_page(int, struct page *, kdev_t, int [], int, int);
 
 typedef long (*writepage_t)(struct file *, struct page *, unsigned long, unsigned long, const char *);
-typedef int (*fs_getblock_t)(struct inode *, unsigned long, struct buffer_head *, int);
+typedef int (*fs_getblock_t)(struct inode *, unsigned long, struct buffer_head *, unsigned int);
+
+#define FS_GETBLK_ALLOCATE     1
+#define FS_GETBLK_UPDATE       2
 
 /* Generic buffer handling for block filesystems.. */
 extern int block_read_full_page(struct file *, struct page *);