Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 17 May 2010 20:54:29 +0000 (13:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 17 May 2010 20:54:29 +0000 (13:54 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k:
  m68k: amiga - Floppy platform device conversion
  m68k: amiga - Sound platform device conversion
  m68k: amiga - Frame buffer platform device conversion
  m68k: amiga - Zorro host bridge platform device conversion
  m68k: amiga - Zorro bus modalias support
  platform: Make platform resource input parameters const
  m68k: invoke oom-killer from page fault
  serial167: Kill unused variables
  m68k: Implement generic_find_next_{zero_,}le_bit()
  m68k: hp300 - Checkpatch cleanup
  m68k: Remove trailing spaces in messages
  m68k: Simplify param.h by using <asm-generic/param.h>
  m68k: Remove BKL from rtc implementations

32 files changed:
arch/alpha/include/asm/atomic.h
arch/arm/include/asm/atomic.h
arch/avr32/include/asm/atomic.h
arch/cris/include/asm/atomic.h
arch/frv/include/asm/atomic.h
arch/h8300/include/asm/atomic.h
arch/ia64/include/asm/atomic.h
arch/m32r/include/asm/atomic.h
arch/m68k/include/asm/atomic_mm.h
arch/m68k/include/asm/atomic_no.h
arch/mips/include/asm/atomic.h
arch/mn10300/include/asm/atomic.h
arch/parisc/include/asm/atomic.h
arch/sh/include/asm/atomic.h
arch/sparc/include/asm/atomic_32.h
arch/sparc/include/asm/atomic_64.h
arch/x86/include/asm/atomic.h
arch/x86/include/asm/atomic64_64.h
arch/xtensa/include/asm/atomic.h
fs/logfs/dev_bdev.c
fs/logfs/dev_mtd.c
fs/logfs/file.c
fs/logfs/gc.c
fs/logfs/inode.c
fs/logfs/journal.c
fs/logfs/logfs.h
fs/logfs/readwrite.c
fs/logfs/segment.c
fs/logfs/super.c
include/asm-generic/atomic.h
include/linux/types.h
kernel/ptrace.c

index 610dff4..e756d04 100644 (file)
@@ -17,8 +17,8 @@
 #define ATOMIC_INIT(i)         ( (atomic_t) { (i) } )
 #define ATOMIC64_INIT(i)       ( (atomic64_t) { (i) } )
 
-#define atomic_read(v)         ((v)->counter + 0)
-#define atomic64_read(v)       ((v)->counter + 0)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
+#define atomic64_read(v)       (*(volatile long *)&(v)->counter)
 
 #define atomic_set(v,i)                ((v)->counter = (i))
 #define atomic64_set(v,i)      ((v)->counter = (i))
index e8ddec2..a0162fa 100644 (file)
@@ -24,7 +24,7 @@
  * strex/ldrex monitor on some implementations. The reason we can use it for
  * atomic_set() is the clrex or dummy strex done on every exception return.
  */
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
 #define atomic_set(v,i)        (((v)->counter) = (i))
 
 #if __LINUX_ARM_ARCH__ >= 6
index b131c27..bbce6a1 100644 (file)
@@ -19,7 +19,7 @@
 
 #define ATOMIC_INIT(i)  { (i) }
 
-#define atomic_read(v)         ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v, i)       (((v)->counter) = i)
 
 /*
index a6aca81..88dc9b9 100644 (file)
@@ -15,7 +15,7 @@
 
 #define ATOMIC_INIT(i)  { (i) }
 
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
 #define atomic_set(v,i) (((v)->counter) = (i))
 
 /* These should be written in asm but we do it in C for now. */
index 00a57af..fae32c7 100644 (file)
@@ -36,7 +36,7 @@
 #define smp_mb__after_atomic_inc()     barrier()
 
 #define ATOMIC_INIT(i)         { (i) }
-#define atomic_read(v)         ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v, i)       (((v)->counter) = (i))
 
 #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
index 33c8c0f..e936804 100644 (file)
@@ -10,7 +10,7 @@
 
 #define ATOMIC_INIT(i) { (i) }
 
-#define atomic_read(v)         ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v, i)       (((v)->counter) = i)
 
 #include <asm/system.h>
index 88405cb..4e19484 100644 (file)
@@ -21,8 +21,8 @@
 #define ATOMIC_INIT(i)         ((atomic_t) { (i) })
 #define ATOMIC64_INIT(i)       ((atomic64_t) { (i) })
 
-#define atomic_read(v)         ((v)->counter)
-#define atomic64_read(v)       ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
+#define atomic64_read(v)       (*(volatile long *)&(v)->counter)
 
 #define atomic_set(v,i)                (((v)->counter) = (i))
 #define atomic64_set(v,i)      (((v)->counter) = (i))
index 63f0cf0..d44a51e 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Atomically reads the value of @v.
  */
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
 
 /**
  * atomic_set - set atomic variable
index d9d2ed6..6a223b3 100644 (file)
@@ -15,7 +15,7 @@
 
 #define ATOMIC_INIT(i) { (i) }
 
-#define atomic_read(v)         ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v, i)       (((v)->counter) = i)
 
 static inline void atomic_add(int i, atomic_t *v)
index 5674cb9..289310c 100644 (file)
@@ -15,7 +15,7 @@
 
 #define ATOMIC_INIT(i) { (i) }
 
-#define atomic_read(v)         ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v, i)       (((v)->counter) = i)
 
 static __inline__ void atomic_add(int i, atomic_t *v)
index 519197e..59dc0c7 100644 (file)
@@ -29,7 +29,7 @@
  *
  * Atomically reads the value of @v.
  */
-#define atomic_read(v)         ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
 
 /*
  * atomic_set - set atomic variable
@@ -410,7 +410,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
  * @v: pointer of type atomic64_t
  *
  */
-#define atomic64_read(v)       ((v)->counter)
+#define atomic64_read(v)       (*(volatile long *)&(v)->counter)
 
 /*
  * atomic64_set - set atomic variable
index 5bf5be9..e41222d 100644 (file)
@@ -31,7 +31,7 @@
  * Atomically reads the value of @v.  Note that the guaranteed
  * useful range of an atomic_t is only 24 bits.
  */
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
 
 /**
  * atomic_set - set atomic variable
index 716634d..f819559 100644 (file)
@@ -189,7 +189,7 @@ static __inline__ void atomic_set(atomic_t *v, int i)
 
 static __inline__ int atomic_read(const atomic_t *v)
 {
-       return v->counter;
+       return (*(volatile int *)&(v)->counter);
 }
 
 /* exported interface */
@@ -286,7 +286,7 @@ atomic64_set(atomic64_t *v, s64 i)
 static __inline__ s64
 atomic64_read(const atomic64_t *v)
 {
-       return v->counter;
+       return (*(volatile long *)&(v)->counter);
 }
 
 #define atomic64_add(i,v)      ((void)(__atomic64_add_return( ((s64)(i)),(v))))
index 275a448..c798312 100644 (file)
@@ -13,7 +13,7 @@
 
 #define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
 
-#define atomic_read(v)         ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v,i)                ((v)->counter = (i))
 
 #if defined(CONFIG_GUSA_RB)
index f0d343c..7ae128b 100644 (file)
@@ -25,7 +25,7 @@ extern int atomic_cmpxchg(atomic_t *, int, int);
 extern int atomic_add_unless(atomic_t *, int, int);
 extern void atomic_set(atomic_t *, int);
 
-#define atomic_read(v)          ((v)->counter)
+#define atomic_read(v)          (*(volatile int *)&(v)->counter)
 
 #define atomic_add(i, v)       ((void)__atomic_add_return( (int)(i), (v)))
 #define atomic_sub(i, v)       ((void)__atomic_add_return(-(int)(i), (v)))
index f2e4800..2050ca0 100644 (file)
@@ -13,8 +13,8 @@
 #define ATOMIC_INIT(i)         { (i) }
 #define ATOMIC64_INIT(i)       { (i) }
 
-#define atomic_read(v)         ((v)->counter)
-#define atomic64_read(v)       ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
+#define atomic64_read(v)       (*(volatile long *)&(v)->counter)
 
 #define atomic_set(v, i)       (((v)->counter) = i)
 #define atomic64_set(v, i)     (((v)->counter) = i)
index 8f8217b..37b39d2 100644 (file)
@@ -22,7 +22,7 @@
  */
 static inline int atomic_read(const atomic_t *v)
 {
-       return v->counter;
+       return (*(volatile int *)&(v)->counter);
 }
 
 /**
index 51c5b40..b014e23 100644 (file)
@@ -18,7 +18,7 @@
  */
 static inline long atomic64_read(const atomic64_t *v)
 {
-       return v->counter;
+       return (*(volatile long *)&(v)->counter);
 }
 
 /**
index 22d6dde..a96a061 100644 (file)
@@ -46,7 +46,7 @@
  *
  * Atomically reads the value of @v.
  */
-#define atomic_read(v)         ((v)->counter)
+#define atomic_read(v)         (*(volatile int *)&(v)->counter)
 
 /**
  * atomic_set - set atomic variable
index 243c000..9bd2ce2 100644 (file)
@@ -303,6 +303,11 @@ static void bdev_put_device(struct super_block *sb)
        close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE);
 }
 
+static int bdev_can_write_buf(struct super_block *sb, u64 ofs)
+{
+       return 0;
+}
+
 static const struct logfs_device_ops bd_devops = {
        .find_first_sb  = bdev_find_first_sb,
        .find_last_sb   = bdev_find_last_sb,
@@ -310,6 +315,7 @@ static const struct logfs_device_ops bd_devops = {
        .readpage       = bdev_readpage,
        .writeseg       = bdev_writeseg,
        .erase          = bdev_erase,
+       .can_write_buf  = bdev_can_write_buf,
        .sync           = bdev_sync,
        .put_device     = bdev_put_device,
 };
index cafb6ef..a85d47d 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/completion.h>
 #include <linux/mount.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
 
@@ -126,7 +127,8 @@ static int mtd_readpage(void *_sb, struct page *page)
 
        err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE,
                        page_address(page));
-       if (err == -EUCLEAN) {
+       if (err == -EUCLEAN || err == -EBADMSG) {
+               /* -EBADMSG happens regularly on power failures */
                err = 0;
                /* FIXME: force GC this segment */
        }
@@ -233,12 +235,32 @@ static void mtd_put_device(struct super_block *sb)
        put_mtd_device(logfs_super(sb)->s_mtd);
 }
 
+static int mtd_can_write_buf(struct super_block *sb, u64 ofs)
+{
+       struct logfs_super *super = logfs_super(sb);
+       void *buf;
+       int err;
+
+       buf = kmalloc(super->s_writesize, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       err = mtd_read(sb, ofs, super->s_writesize, buf);
+       if (err)
+               goto out;
+       if (memchr_inv(buf, 0xff, super->s_writesize))
+               err = -EIO;
+       kfree(buf);
+out:
+       return err;
+}
+
 static const struct logfs_device_ops mtd_devops = {
        .find_first_sb  = mtd_find_first_sb,
        .find_last_sb   = mtd_find_last_sb,
        .readpage       = mtd_readpage,
        .writeseg       = mtd_writeseg,
        .erase          = mtd_erase,
+       .can_write_buf  = mtd_can_write_buf,
        .sync           = mtd_sync,
        .put_device     = mtd_put_device,
 };
@@ -250,5 +272,7 @@ int logfs_get_sb_mtd(struct file_system_type *type, int flags,
        const struct logfs_device_ops *devops = &mtd_devops;
 
        mtd = get_mtd_device(NULL, mtdnr);
+       if (IS_ERR(mtd))
+               return PTR_ERR(mtd);
        return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt);
 }
index 370f367..0de5240 100644 (file)
@@ -161,7 +161,17 @@ static int logfs_writepage(struct page *page, struct writeback_control *wbc)
 
 static void logfs_invalidatepage(struct page *page, unsigned long offset)
 {
-       move_page_to_btree(page);
+       struct logfs_block *block = logfs_block(page);
+
+       if (block->reserved_bytes) {
+               struct super_block *sb = page->mapping->host->i_sb;
+               struct logfs_super *super = logfs_super(sb);
+
+               super->s_dirty_pages -= block->reserved_bytes;
+               block->ops->free_block(sb, block);
+               BUG_ON(bitmap_weight(block->alias_map, LOGFS_BLOCK_FACTOR));
+       } else
+               move_page_to_btree(page);
        BUG_ON(PagePrivate(page) || page->private);
 }
 
@@ -212,10 +222,8 @@ int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 int logfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
        struct super_block *sb = dentry->d_inode->i_sb;
-       struct logfs_super *super = logfs_super(sb);
 
-       /* FIXME: write anchor */
-       super->s_devops->sync(sb);
+       logfs_write_anchor(sb);
        return 0;
 }
 
index 76c242f..caa4419 100644 (file)
@@ -122,7 +122,7 @@ static void logfs_cleanse_block(struct super_block *sb, u64 ofs, u64 ino,
        logfs_safe_iput(inode, cookie);
 }
 
-static u32 logfs_gc_segment(struct super_block *sb, u32 segno, u8 dist)
+static u32 logfs_gc_segment(struct super_block *sb, u32 segno)
 {
        struct logfs_super *super = logfs_super(sb);
        struct logfs_segment_header sh;
@@ -401,7 +401,7 @@ static int __logfs_gc_once(struct super_block *sb, struct gc_candidate *cand)
                        segno, (u64)segno << super->s_segshift,
                        dist, no_free_segments(sb), valid,
                        super->s_free_bytes);
-       cleaned = logfs_gc_segment(sb, segno, dist);
+       cleaned = logfs_gc_segment(sb, segno);
        log_gc("GC segment #%02x complete - now %x valid\n", segno,
                        valid - cleaned);
        BUG_ON(cleaned != valid);
@@ -632,38 +632,31 @@ static int check_area(struct super_block *sb, int i)
 {
        struct logfs_super *super = logfs_super(sb);
        struct logfs_area *area = super->s_area[i];
-       struct logfs_object_header oh;
+       gc_level_t gc_level;
+       u32 cleaned, valid, ec;
        u32 segno = area->a_segno;
-       u32 ofs = area->a_used_bytes;
-       __be32 crc;
-       int err;
+       u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
 
        if (!area->a_is_open)
                return 0;
 
-       for (ofs = area->a_used_bytes;
-            ofs <= super->s_segsize - sizeof(oh);
-            ofs += (u32)be16_to_cpu(oh.len) + sizeof(oh)) {
-               err = wbuf_read(sb, dev_ofs(sb, segno, ofs), sizeof(oh), &oh);
-               if (err)
-                       return err;
-
-               if (!memchr_inv(&oh, 0xff, sizeof(oh)))
-                       break;
+       if (super->s_devops->can_write_buf(sb, ofs) == 0)
+               return 0;
 
-               crc = logfs_crc32(&oh, sizeof(oh) - 4, 4);
-               if (crc != oh.crc) {
-                       printk(KERN_INFO "interrupted header at %llx\n",
-                                       dev_ofs(sb, segno, ofs));
-                       return 0;
-               }
-       }
-       if (ofs != area->a_used_bytes) {
-               printk(KERN_INFO "%x bytes unaccounted data found at %llx\n",
-                               ofs - area->a_used_bytes,
-                               dev_ofs(sb, segno, area->a_used_bytes));
-               area->a_used_bytes = ofs;
-       }
+       printk(KERN_INFO"LogFS: Possibly incomplete write at %llx\n", ofs);
+       /*
+        * The device cannot write back the write buffer.  Most likely the
+        * wbuf was already written out and the system crashed at some point
+        * before the journal commit happened.  In that case we wouldn't have
+        * to do anything.  But if the crash happened before the wbuf was
+        * written out correctly, we must GC this segment.  So assume the
+        * worst and always do the GC run.
+        */
+       area->a_is_open = 0;
+       valid = logfs_valid_bytes(sb, segno, &ec, &gc_level);
+       cleaned = logfs_gc_segment(sb, segno);
+       if (cleaned != valid)
+               return -EIO;
        return 0;
 }
 
index 14ed272..755a92e 100644 (file)
@@ -193,6 +193,7 @@ static void logfs_init_inode(struct super_block *sb, struct inode *inode)
        inode->i_ctime  = CURRENT_TIME;
        inode->i_mtime  = CURRENT_TIME;
        inode->i_nlink  = 1;
+       li->li_refcount = 1;
        INIT_LIST_HEAD(&li->li_freeing_list);
 
        for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
@@ -326,7 +327,7 @@ static void logfs_set_ino_generation(struct super_block *sb,
        u64 ino;
 
        mutex_lock(&super->s_journal_mutex);
-       ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino);
+       ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino + 1);
        super->s_last_ino = ino;
        super->s_inos_till_wrap--;
        if (super->s_inos_till_wrap < 0) {
@@ -386,8 +387,7 @@ static void logfs_init_once(void *_li)
 
 static int logfs_sync_fs(struct super_block *sb, int wait)
 {
-       /* FIXME: write anchor */
-       logfs_super(sb)->s_devops->sync(sb);
+       logfs_write_anchor(sb);
        return 0;
 }
 
index fb0a613..4b0e061 100644 (file)
@@ -132,10 +132,9 @@ static int read_area(struct super_block *sb, struct logfs_je_area *a)
 
        ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
        if (super->s_writesize > 1)
-               logfs_buf_recover(area, ofs, a + 1, super->s_writesize);
+               return logfs_buf_recover(area, ofs, a + 1, super->s_writesize);
        else
-               logfs_buf_recover(area, ofs, NULL, 0);
-       return 0;
+               return logfs_buf_recover(area, ofs, NULL, 0);
 }
 
 static void *unpack(void *from, void *to)
@@ -245,7 +244,7 @@ static int read_je(struct super_block *sb, u64 ofs)
                read_erasecount(sb, unpack(jh, scratch));
                break;
        case JE_AREA:
-               read_area(sb, unpack(jh, scratch));
+               err = read_area(sb, unpack(jh, scratch));
                break;
        case JE_OBJ_ALIAS:
                err = logfs_load_object_aliases(sb, unpack(jh, scratch),
index 0a3df1a..93b55f3 100644 (file)
@@ -144,6 +144,7 @@ struct logfs_area_ops {
  * @erase:                     erase one segment
  * @read:                      read from the device
  * @erase:                     erase part of the device
+ * @can_write_buf:             decide whether wbuf can be written to ofs
  */
 struct logfs_device_ops {
        struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs);
@@ -153,6 +154,7 @@ struct logfs_device_ops {
        void (*writeseg)(struct super_block *sb, u64 ofs, size_t len);
        int (*erase)(struct super_block *sb, loff_t ofs, size_t len,
                        int ensure_write);
+       int (*can_write_buf)(struct super_block *sb, u64 ofs);
        void (*sync)(struct super_block *sb);
        void (*put_device)(struct super_block *sb);
 };
@@ -394,6 +396,7 @@ struct logfs_super {
        int      s_lock_count;
        mempool_t *s_block_pool;                /* struct logfs_block pool */
        mempool_t *s_shadow_pool;               /* struct logfs_shadow pool */
+       struct list_head s_writeback_list;      /* writeback pages */
        /*
         * Space accounting:
         * - s_used_bytes specifies space used to store valid data objects.
@@ -598,19 +601,19 @@ void freeseg(struct super_block *sb, u32 segno);
 int logfs_init_areas(struct super_block *sb);
 void logfs_cleanup_areas(struct super_block *sb);
 int logfs_open_area(struct logfs_area *area, size_t bytes);
-void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
+int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
                int use_filler);
 
-static inline void logfs_buf_write(struct logfs_area *area, u64 ofs,
+static inline int logfs_buf_write(struct logfs_area *area, u64 ofs,
                void *buf, size_t len)
 {
-       __logfs_buf_write(area, ofs, buf, len, 0);
+       return __logfs_buf_write(area, ofs, buf, len, 0);
 }
 
-static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs,
+static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs,
                void *buf, size_t len)
 {
-       __logfs_buf_write(area, ofs, buf, len, 1);
+       return __logfs_buf_write(area, ofs, buf, len, 1);
 }
 
 /* super.c */
index 3159db6..0718d11 100644 (file)
@@ -892,6 +892,8 @@ u64 logfs_seek_hole(struct inode *inode, u64 bix)
                return bix;
        else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED)
                bix = maxbix(li->li_height);
+       else if (bix >= maxbix(li->li_height))
+               return bix;
        else {
                bix = seek_holedata_loop(inode, bix, 0);
                if (bix < maxbix(li->li_height))
@@ -1093,17 +1095,25 @@ static int logfs_reserve_bytes(struct inode *inode, int bytes)
 int get_page_reserve(struct inode *inode, struct page *page)
 {
        struct logfs_super *super = logfs_super(inode->i_sb);
+       struct logfs_block *block = logfs_block(page);
        int ret;
 
-       if (logfs_block(page) && logfs_block(page)->reserved_bytes)
+       if (block && block->reserved_bytes)
                return 0;
 
        logfs_get_wblocks(inode->i_sb, page, WF_LOCK);
-       ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE);
+       while ((ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE)) &&
+                       !list_empty(&super->s_writeback_list)) {
+               block = list_entry(super->s_writeback_list.next,
+                               struct logfs_block, alias_list);
+               block->ops->write_block(block);
+       }
        if (!ret) {
                alloc_data_block(inode, page);
-               logfs_block(page)->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE;
+               block = logfs_block(page);
+               block->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE;
                super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE;
+               list_move_tail(&block->alias_list, &super->s_writeback_list);
        }
        logfs_put_wblocks(inode->i_sb, page, WF_LOCK);
        return ret;
@@ -1861,7 +1871,7 @@ int logfs_truncate(struct inode *inode, u64 target)
                        size = target;
 
                logfs_get_wblocks(sb, NULL, 1);
-               err = __logfs_truncate(inode, target);
+               err = __logfs_truncate(inode, size);
                if (!err)
                        err = __logfs_write_inode(inode, 0);
                logfs_put_wblocks(sb, NULL, 1);
@@ -2249,6 +2259,7 @@ int logfs_init_rw(struct super_block *sb)
        int min_fill = 3 * super->s_no_blocks;
 
        INIT_LIST_HEAD(&super->s_object_alias);
+       INIT_LIST_HEAD(&super->s_writeback_list);
        mutex_init(&super->s_write_mutex);
        super->s_block_pool = mempool_create_kmalloc_pool(min_fill,
                        sizeof(struct logfs_block));
index f77ce2b..a9657af 100644 (file)
@@ -67,7 +67,7 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index,
        return page;
 }
 
-void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
+int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
                int use_filler)
 {
        pgoff_t index = ofs >> PAGE_SHIFT;
@@ -81,8 +81,10 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
                copylen = min((ulong)len, PAGE_SIZE - offset);
 
                page = get_mapping_page(area->a_sb, index, use_filler);
-               SetPageUptodate(page);
+               if (IS_ERR(page))
+                       return PTR_ERR(page);
                BUG_ON(!page); /* FIXME: reserve a pool */
+               SetPageUptodate(page);
                memcpy(page_address(page) + offset, buf, copylen);
                SetPagePrivate(page);
                page_cache_release(page);
@@ -92,6 +94,7 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
                offset = 0;
                index++;
        } while (len);
+       return 0;
 }
 
 static void pad_partial_page(struct logfs_area *area)
index d7c23ed..d651e10 100644 (file)
@@ -138,10 +138,14 @@ static int logfs_sb_set(struct super_block *sb, void *_super)
        sb->s_fs_info = super;
        sb->s_mtd = super->s_mtd;
        sb->s_bdev = super->s_bdev;
+#ifdef CONFIG_BLOCK
        if (sb->s_bdev)
                sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info;
+#endif
+#ifdef CONFIG_MTD
        if (sb->s_mtd)
                sb->s_bdi = sb->s_mtd->backing_dev_info;
+#endif
        return 0;
 }
 
@@ -382,7 +386,7 @@ static struct page *find_super_block(struct super_block *sb)
        if (!first || IS_ERR(first))
                return NULL;
        last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]);
-       if (!last || IS_ERR(first)) {
+       if (!last || IS_ERR(last)) {
                page_cache_release(first);
                return NULL;
        }
@@ -413,7 +417,7 @@ static int __logfs_read_sb(struct super_block *sb)
 
        page = find_super_block(sb);
        if (!page)
-               return -EIO;
+               return -EINVAL;
 
        ds = page_address(page);
        super->s_size = be64_to_cpu(ds->ds_filesystem_size);
index c99c64d..c33749f 100644 (file)
@@ -33,7 +33,7 @@
  * Atomically reads the value of @v.  Note that the guaranteed
  * useful range of an atomic_t is only 24 bits.
  */
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
 
 /**
  * atomic_set - set atomic variable
index c42724f..23d237a 100644 (file)
@@ -188,12 +188,12 @@ typedef u32 phys_addr_t;
 typedef phys_addr_t resource_size_t;
 
 typedef struct {
-       volatile int counter;
+       int counter;
 } atomic_t;
 
 #ifdef CONFIG_64BIT
 typedef struct {
-       volatile long counter;
+       long counter;
 } atomic64_t;
 #endif
 
index 42ad8ae..2f0f50b 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/security.h>
 #include <linux/signal.h>
@@ -666,10 +665,6 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data)
        struct task_struct *child;
        long ret;
 
-       /*
-        * This lock_kernel fixes a subtle race with suid exec
-        */
-       lock_kernel();
        if (request == PTRACE_TRACEME) {
                ret = ptrace_traceme();
                if (!ret)
@@ -703,7 +698,6 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data)
  out_put_task_struct:
        put_task_struct(child);
  out:
-       unlock_kernel();
        return ret;
 }
 
@@ -813,10 +807,6 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
        struct task_struct *child;
        long ret;
 
-       /*
-        * This lock_kernel fixes a subtle race with suid exec
-        */
-       lock_kernel();
        if (request == PTRACE_TRACEME) {
                ret = ptrace_traceme();
                goto out;
@@ -846,7 +836,6 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
  out_put_task_struct:
        put_task_struct(child);
  out:
-       unlock_kernel();
        return ret;
 }
 #endif /* CONFIG_COMPAT */