diff options
32 files changed, 131 insertions, 91 deletions
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index 610dff44d94..e756d04b6cd 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h | |||
@@ -17,8 +17,8 @@ | |||
17 | #define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) | 17 | #define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) |
18 | #define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) | 18 | #define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) |
19 | 19 | ||
20 | #define atomic_read(v) ((v)->counter + 0) | 20 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
21 | #define atomic64_read(v) ((v)->counter + 0) | 21 | #define atomic64_read(v) (*(volatile long *)&(v)->counter) |
22 | 22 | ||
23 | #define atomic_set(v,i) ((v)->counter = (i)) | 23 | #define atomic_set(v,i) ((v)->counter = (i)) |
24 | #define atomic64_set(v,i) ((v)->counter = (i)) | 24 | #define atomic64_set(v,i) ((v)->counter = (i)) |
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index e8ddec2cb15..a0162fa9456 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h | |||
@@ -24,7 +24,7 @@ | |||
24 | * strex/ldrex monitor on some implementations. The reason we can use it for | 24 | * strex/ldrex monitor on some implementations. The reason we can use it for |
25 | * atomic_set() is the clrex or dummy strex done on every exception return. | 25 | * atomic_set() is the clrex or dummy strex done on every exception return. |
26 | */ | 26 | */ |
27 | #define atomic_read(v) ((v)->counter) | 27 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
28 | #define atomic_set(v,i) (((v)->counter) = (i)) | 28 | #define atomic_set(v,i) (((v)->counter) = (i)) |
29 | 29 | ||
30 | #if __LINUX_ARM_ARCH__ >= 6 | 30 | #if __LINUX_ARM_ARCH__ >= 6 |
diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h index b131c27ddf5..bbce6a1c6bb 100644 --- a/arch/avr32/include/asm/atomic.h +++ b/arch/avr32/include/asm/atomic.h | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | #define ATOMIC_INIT(i) { (i) } | 20 | #define ATOMIC_INIT(i) { (i) } |
21 | 21 | ||
22 | #define atomic_read(v) ((v)->counter) | 22 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
23 | #define atomic_set(v, i) (((v)->counter) = i) | 23 | #define atomic_set(v, i) (((v)->counter) = i) |
24 | 24 | ||
25 | /* | 25 | /* |
diff --git a/arch/cris/include/asm/atomic.h b/arch/cris/include/asm/atomic.h index a6aca819e9f..88dc9b9c4ba 100644 --- a/arch/cris/include/asm/atomic.h +++ b/arch/cris/include/asm/atomic.h | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #define ATOMIC_INIT(i) { (i) } | 16 | #define ATOMIC_INIT(i) { (i) } |
17 | 17 | ||
18 | #define atomic_read(v) ((v)->counter) | 18 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
19 | #define atomic_set(v,i) (((v)->counter) = (i)) | 19 | #define atomic_set(v,i) (((v)->counter) = (i)) |
20 | 20 | ||
21 | /* These should be written in asm but we do it in C for now. */ | 21 | /* These should be written in asm but we do it in C for now. */ |
diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h index 00a57af79af..fae32c7fdcb 100644 --- a/arch/frv/include/asm/atomic.h +++ b/arch/frv/include/asm/atomic.h | |||
@@ -36,7 +36,7 @@ | |||
36 | #define smp_mb__after_atomic_inc() barrier() | 36 | #define smp_mb__after_atomic_inc() barrier() |
37 | 37 | ||
38 | #define ATOMIC_INIT(i) { (i) } | 38 | #define ATOMIC_INIT(i) { (i) } |
39 | #define atomic_read(v) ((v)->counter) | 39 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
40 | #define atomic_set(v, i) (((v)->counter) = (i)) | 40 | #define atomic_set(v, i) (((v)->counter) = (i)) |
41 | 41 | ||
42 | #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS | 42 | #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS |
diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h index 33c8c0fa958..e936804b750 100644 --- a/arch/h8300/include/asm/atomic.h +++ b/arch/h8300/include/asm/atomic.h | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | #define ATOMIC_INIT(i) { (i) } | 11 | #define ATOMIC_INIT(i) { (i) } |
12 | 12 | ||
13 | #define atomic_read(v) ((v)->counter) | 13 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
14 | #define atomic_set(v, i) (((v)->counter) = i) | 14 | #define atomic_set(v, i) (((v)->counter) = i) |
15 | 15 | ||
16 | #include <asm/system.h> | 16 | #include <asm/system.h> |
diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h index 88405cb0832..4e1948447a0 100644 --- a/arch/ia64/include/asm/atomic.h +++ b/arch/ia64/include/asm/atomic.h | |||
@@ -21,8 +21,8 @@ | |||
21 | #define ATOMIC_INIT(i) ((atomic_t) { (i) }) | 21 | #define ATOMIC_INIT(i) ((atomic_t) { (i) }) |
22 | #define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) | 22 | #define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) |
23 | 23 | ||
24 | #define atomic_read(v) ((v)->counter) | 24 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
25 | #define atomic64_read(v) ((v)->counter) | 25 | #define atomic64_read(v) (*(volatile long *)&(v)->counter) |
26 | 26 | ||
27 | #define atomic_set(v,i) (((v)->counter) = (i)) | 27 | #define atomic_set(v,i) (((v)->counter) = (i)) |
28 | #define atomic64_set(v,i) (((v)->counter) = (i)) | 28 | #define atomic64_set(v,i) (((v)->counter) = (i)) |
diff --git a/arch/m32r/include/asm/atomic.h b/arch/m32r/include/asm/atomic.h index 63f0cf0f50d..d44a51e5271 100644 --- a/arch/m32r/include/asm/atomic.h +++ b/arch/m32r/include/asm/atomic.h | |||
@@ -26,7 +26,7 @@ | |||
26 | * | 26 | * |
27 | * Atomically reads the value of @v. | 27 | * Atomically reads the value of @v. |
28 | */ | 28 | */ |
29 | #define atomic_read(v) ((v)->counter) | 29 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * atomic_set - set atomic variable | 32 | * atomic_set - set atomic variable |
diff --git a/arch/m68k/include/asm/atomic_mm.h b/arch/m68k/include/asm/atomic_mm.h index d9d2ed64743..6a223b3f7e7 100644 --- a/arch/m68k/include/asm/atomic_mm.h +++ b/arch/m68k/include/asm/atomic_mm.h | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #define ATOMIC_INIT(i) { (i) } | 16 | #define ATOMIC_INIT(i) { (i) } |
17 | 17 | ||
18 | #define atomic_read(v) ((v)->counter) | 18 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
19 | #define atomic_set(v, i) (((v)->counter) = i) | 19 | #define atomic_set(v, i) (((v)->counter) = i) |
20 | 20 | ||
21 | static inline void atomic_add(int i, atomic_t *v) | 21 | static inline void atomic_add(int i, atomic_t *v) |
diff --git a/arch/m68k/include/asm/atomic_no.h b/arch/m68k/include/asm/atomic_no.h index 5674cb9449b..289310c63a8 100644 --- a/arch/m68k/include/asm/atomic_no.h +++ b/arch/m68k/include/asm/atomic_no.h | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #define ATOMIC_INIT(i) { (i) } | 16 | #define ATOMIC_INIT(i) { (i) } |
17 | 17 | ||
18 | #define atomic_read(v) ((v)->counter) | 18 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
19 | #define atomic_set(v, i) (((v)->counter) = i) | 19 | #define atomic_set(v, i) (((v)->counter) = i) |
20 | 20 | ||
21 | static __inline__ void atomic_add(int i, atomic_t *v) | 21 | static __inline__ void atomic_add(int i, atomic_t *v) |
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index 519197ede08..59dc0c7ef73 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h | |||
@@ -29,7 +29,7 @@ | |||
29 | * | 29 | * |
30 | * Atomically reads the value of @v. | 30 | * Atomically reads the value of @v. |
31 | */ | 31 | */ |
32 | #define atomic_read(v) ((v)->counter) | 32 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * atomic_set - set atomic variable | 35 | * atomic_set - set atomic variable |
@@ -410,7 +410,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) | |||
410 | * @v: pointer of type atomic64_t | 410 | * @v: pointer of type atomic64_t |
411 | * | 411 | * |
412 | */ | 412 | */ |
413 | #define atomic64_read(v) ((v)->counter) | 413 | #define atomic64_read(v) (*(volatile long *)&(v)->counter) |
414 | 414 | ||
415 | /* | 415 | /* |
416 | * atomic64_set - set atomic variable | 416 | * atomic64_set - set atomic variable |
diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h index 5bf5be9566d..e41222d6c2f 100644 --- a/arch/mn10300/include/asm/atomic.h +++ b/arch/mn10300/include/asm/atomic.h | |||
@@ -31,7 +31,7 @@ | |||
31 | * Atomically reads the value of @v. Note that the guaranteed | 31 | * Atomically reads the value of @v. Note that the guaranteed |
32 | * useful range of an atomic_t is only 24 bits. | 32 | * useful range of an atomic_t is only 24 bits. |
33 | */ | 33 | */ |
34 | #define atomic_read(v) ((v)->counter) | 34 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * atomic_set - set atomic variable | 37 | * atomic_set - set atomic variable |
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 716634d1f54..f81955934ae 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h | |||
@@ -189,7 +189,7 @@ static __inline__ void atomic_set(atomic_t *v, int i) | |||
189 | 189 | ||
190 | static __inline__ int atomic_read(const atomic_t *v) | 190 | static __inline__ int atomic_read(const atomic_t *v) |
191 | { | 191 | { |
192 | return v->counter; | 192 | return (*(volatile int *)&(v)->counter); |
193 | } | 193 | } |
194 | 194 | ||
195 | /* exported interface */ | 195 | /* exported interface */ |
@@ -286,7 +286,7 @@ atomic64_set(atomic64_t *v, s64 i) | |||
286 | static __inline__ s64 | 286 | static __inline__ s64 |
287 | atomic64_read(const atomic64_t *v) | 287 | atomic64_read(const atomic64_t *v) |
288 | { | 288 | { |
289 | return v->counter; | 289 | return (*(volatile long *)&(v)->counter); |
290 | } | 290 | } |
291 | 291 | ||
292 | #define atomic64_add(i,v) ((void)(__atomic64_add_return( ((s64)(i)),(v)))) | 292 | #define atomic64_add(i,v) ((void)(__atomic64_add_return( ((s64)(i)),(v)))) |
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h index 275a448ae8c..c7983124d99 100644 --- a/arch/sh/include/asm/atomic.h +++ b/arch/sh/include/asm/atomic.h | |||
@@ -13,7 +13,7 @@ | |||
13 | 13 | ||
14 | #define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) | 14 | #define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) |
15 | 15 | ||
16 | #define atomic_read(v) ((v)->counter) | 16 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
17 | #define atomic_set(v,i) ((v)->counter = (i)) | 17 | #define atomic_set(v,i) ((v)->counter = (i)) |
18 | 18 | ||
19 | #if defined(CONFIG_GUSA_RB) | 19 | #if defined(CONFIG_GUSA_RB) |
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h index f0d343c3b95..7ae128b19d3 100644 --- a/arch/sparc/include/asm/atomic_32.h +++ b/arch/sparc/include/asm/atomic_32.h | |||
@@ -25,7 +25,7 @@ extern int atomic_cmpxchg(atomic_t *, int, int); | |||
25 | extern int atomic_add_unless(atomic_t *, int, int); | 25 | extern int atomic_add_unless(atomic_t *, int, int); |
26 | extern void atomic_set(atomic_t *, int); | 26 | extern void atomic_set(atomic_t *, int); |
27 | 27 | ||
28 | #define atomic_read(v) ((v)->counter) | 28 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
29 | 29 | ||
30 | #define atomic_add(i, v) ((void)__atomic_add_return( (int)(i), (v))) | 30 | #define atomic_add(i, v) ((void)__atomic_add_return( (int)(i), (v))) |
31 | #define atomic_sub(i, v) ((void)__atomic_add_return(-(int)(i), (v))) | 31 | #define atomic_sub(i, v) ((void)__atomic_add_return(-(int)(i), (v))) |
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index f2e48009989..2050ca02c42 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h | |||
@@ -13,8 +13,8 @@ | |||
13 | #define ATOMIC_INIT(i) { (i) } | 13 | #define ATOMIC_INIT(i) { (i) } |
14 | #define ATOMIC64_INIT(i) { (i) } | 14 | #define ATOMIC64_INIT(i) { (i) } |
15 | 15 | ||
16 | #define atomic_read(v) ((v)->counter) | 16 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
17 | #define atomic64_read(v) ((v)->counter) | 17 | #define atomic64_read(v) (*(volatile long *)&(v)->counter) |
18 | 18 | ||
19 | #define atomic_set(v, i) (((v)->counter) = i) | 19 | #define atomic_set(v, i) (((v)->counter) = i) |
20 | #define atomic64_set(v, i) (((v)->counter) = i) | 20 | #define atomic64_set(v, i) (((v)->counter) = i) |
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index 8f8217b9bda..37b39d27abe 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h | |||
@@ -22,7 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | static inline int atomic_read(const atomic_t *v) | 23 | static inline int atomic_read(const atomic_t *v) |
24 | { | 24 | { |
25 | return v->counter; | 25 | return (*(volatile int *)&(v)->counter); |
26 | } | 26 | } |
27 | 27 | ||
28 | /** | 28 | /** |
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index 51c5b405692..b014e235ea8 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h | |||
@@ -18,7 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | static inline long atomic64_read(const atomic64_t *v) | 19 | static inline long atomic64_read(const atomic64_t *v) |
20 | { | 20 | { |
21 | return v->counter; | 21 | return (*(volatile long *)&(v)->counter); |
22 | } | 22 | } |
23 | 23 | ||
24 | /** | 24 | /** |
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index 22d6dde4261..a96a0619d0b 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h | |||
@@ -46,7 +46,7 @@ | |||
46 | * | 46 | * |
47 | * Atomically reads the value of @v. | 47 | * Atomically reads the value of @v. |
48 | */ | 48 | */ |
49 | #define atomic_read(v) ((v)->counter) | 49 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * atomic_set - set atomic variable | 52 | * atomic_set - set atomic variable |
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index 243c00071f7..9bd2ce2a304 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c | |||
@@ -303,6 +303,11 @@ static void bdev_put_device(struct super_block *sb) | |||
303 | close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE); | 303 | close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE); |
304 | } | 304 | } |
305 | 305 | ||
306 | static int bdev_can_write_buf(struct super_block *sb, u64 ofs) | ||
307 | { | ||
308 | return 0; | ||
309 | } | ||
310 | |||
306 | static const struct logfs_device_ops bd_devops = { | 311 | static const struct logfs_device_ops bd_devops = { |
307 | .find_first_sb = bdev_find_first_sb, | 312 | .find_first_sb = bdev_find_first_sb, |
308 | .find_last_sb = bdev_find_last_sb, | 313 | .find_last_sb = bdev_find_last_sb, |
@@ -310,6 +315,7 @@ static const struct logfs_device_ops bd_devops = { | |||
310 | .readpage = bdev_readpage, | 315 | .readpage = bdev_readpage, |
311 | .writeseg = bdev_writeseg, | 316 | .writeseg = bdev_writeseg, |
312 | .erase = bdev_erase, | 317 | .erase = bdev_erase, |
318 | .can_write_buf = bdev_can_write_buf, | ||
313 | .sync = bdev_sync, | 319 | .sync = bdev_sync, |
314 | .put_device = bdev_put_device, | 320 | .put_device = bdev_put_device, |
315 | }; | 321 | }; |
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index cafb6ef2e05..a85d47d13e4 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/completion.h> | 9 | #include <linux/completion.h> |
10 | #include <linux/mount.h> | 10 | #include <linux/mount.h> |
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/slab.h> | ||
12 | 13 | ||
13 | #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) | 14 | #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) |
14 | 15 | ||
@@ -126,7 +127,8 @@ static int mtd_readpage(void *_sb, struct page *page) | |||
126 | 127 | ||
127 | err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE, | 128 | err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE, |
128 | page_address(page)); | 129 | page_address(page)); |
129 | if (err == -EUCLEAN) { | 130 | if (err == -EUCLEAN || err == -EBADMSG) { |
131 | /* -EBADMSG happens regularly on power failures */ | ||
130 | err = 0; | 132 | err = 0; |
131 | /* FIXME: force GC this segment */ | 133 | /* FIXME: force GC this segment */ |
132 | } | 134 | } |
@@ -233,12 +235,32 @@ static void mtd_put_device(struct super_block *sb) | |||
233 | put_mtd_device(logfs_super(sb)->s_mtd); | 235 | put_mtd_device(logfs_super(sb)->s_mtd); |
234 | } | 236 | } |
235 | 237 | ||
238 | static int mtd_can_write_buf(struct super_block *sb, u64 ofs) | ||
239 | { | ||
240 | struct logfs_super *super = logfs_super(sb); | ||
241 | void *buf; | ||
242 | int err; | ||
243 | |||
244 | buf = kmalloc(super->s_writesize, GFP_KERNEL); | ||
245 | if (!buf) | ||
246 | return -ENOMEM; | ||
247 | err = mtd_read(sb, ofs, super->s_writesize, buf); | ||
248 | if (err) | ||
249 | goto out; | ||
250 | if (memchr_inv(buf, 0xff, super->s_writesize)) | ||
251 | err = -EIO; | ||
252 | kfree(buf); | ||
253 | out: | ||
254 | return err; | ||
255 | } | ||
256 | |||
236 | static const struct logfs_device_ops mtd_devops = { | 257 | static const struct logfs_device_ops mtd_devops = { |
237 | .find_first_sb = mtd_find_first_sb, | 258 | .find_first_sb = mtd_find_first_sb, |
238 | .find_last_sb = mtd_find_last_sb, | 259 | .find_last_sb = mtd_find_last_sb, |
239 | .readpage = mtd_readpage, | 260 | .readpage = mtd_readpage, |
240 | .writeseg = mtd_writeseg, | 261 | .writeseg = mtd_writeseg, |
241 | .erase = mtd_erase, | 262 | .erase = mtd_erase, |
263 | .can_write_buf = mtd_can_write_buf, | ||
242 | .sync = mtd_sync, | 264 | .sync = mtd_sync, |
243 | .put_device = mtd_put_device, | 265 | .put_device = mtd_put_device, |
244 | }; | 266 | }; |
@@ -250,5 +272,7 @@ int logfs_get_sb_mtd(struct file_system_type *type, int flags, | |||
250 | const struct logfs_device_ops *devops = &mtd_devops; | 272 | const struct logfs_device_ops *devops = &mtd_devops; |
251 | 273 | ||
252 | mtd = get_mtd_device(NULL, mtdnr); | 274 | mtd = get_mtd_device(NULL, mtdnr); |
275 | if (IS_ERR(mtd)) | ||
276 | return PTR_ERR(mtd); | ||
253 | return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt); | 277 | return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt); |
254 | } | 278 | } |
diff --git a/fs/logfs/file.c b/fs/logfs/file.c index 370f367a933..0de52407187 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c | |||
@@ -161,7 +161,17 @@ static int logfs_writepage(struct page *page, struct writeback_control *wbc) | |||
161 | 161 | ||
162 | static void logfs_invalidatepage(struct page *page, unsigned long offset) | 162 | static void logfs_invalidatepage(struct page *page, unsigned long offset) |
163 | { | 163 | { |
164 | move_page_to_btree(page); | 164 | struct logfs_block *block = logfs_block(page); |
165 | |||
166 | if (block->reserved_bytes) { | ||
167 | struct super_block *sb = page->mapping->host->i_sb; | ||
168 | struct logfs_super *super = logfs_super(sb); | ||
169 | |||
170 | super->s_dirty_pages -= block->reserved_bytes; | ||
171 | block->ops->free_block(sb, block); | ||
172 | BUG_ON(bitmap_weight(block->alias_map, LOGFS_BLOCK_FACTOR)); | ||
173 | } else | ||
174 | move_page_to_btree(page); | ||
165 | BUG_ON(PagePrivate(page) || page->private); | 175 | BUG_ON(PagePrivate(page) || page->private); |
166 | } | 176 | } |
167 | 177 | ||
@@ -212,10 +222,8 @@ int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
212 | int logfs_fsync(struct file *file, struct dentry *dentry, int datasync) | 222 | int logfs_fsync(struct file *file, struct dentry *dentry, int datasync) |
213 | { | 223 | { |
214 | struct super_block *sb = dentry->d_inode->i_sb; | 224 | struct super_block *sb = dentry->d_inode->i_sb; |
215 | struct logfs_super *super = logfs_super(sb); | ||
216 | 225 | ||
217 | /* FIXME: write anchor */ | 226 | logfs_write_anchor(sb); |
218 | super->s_devops->sync(sb); | ||
219 | return 0; | 227 | return 0; |
220 | } | 228 | } |
221 | 229 | ||
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c index 76c242fbe1b..caa4419285d 100644 --- a/fs/logfs/gc.c +++ b/fs/logfs/gc.c | |||
@@ -122,7 +122,7 @@ static void logfs_cleanse_block(struct super_block *sb, u64 ofs, u64 ino, | |||
122 | logfs_safe_iput(inode, cookie); | 122 | logfs_safe_iput(inode, cookie); |
123 | } | 123 | } |
124 | 124 | ||
125 | static u32 logfs_gc_segment(struct super_block *sb, u32 segno, u8 dist) | 125 | static u32 logfs_gc_segment(struct super_block *sb, u32 segno) |
126 | { | 126 | { |
127 | struct logfs_super *super = logfs_super(sb); | 127 | struct logfs_super *super = logfs_super(sb); |
128 | struct logfs_segment_header sh; | 128 | struct logfs_segment_header sh; |
@@ -401,7 +401,7 @@ static int __logfs_gc_once(struct super_block *sb, struct gc_candidate *cand) | |||
401 | segno, (u64)segno << super->s_segshift, | 401 | segno, (u64)segno << super->s_segshift, |
402 | dist, no_free_segments(sb), valid, | 402 | dist, no_free_segments(sb), valid, |
403 | super->s_free_bytes); | 403 | super->s_free_bytes); |
404 | cleaned = logfs_gc_segment(sb, segno, dist); | 404 | cleaned = logfs_gc_segment(sb, segno); |
405 | log_gc("GC segment #%02x complete - now %x valid\n", segno, | 405 | log_gc("GC segment #%02x complete - now %x valid\n", segno, |
406 | valid - cleaned); | 406 | valid - cleaned); |
407 | BUG_ON(cleaned != valid); | 407 | BUG_ON(cleaned != valid); |
@@ -632,38 +632,31 @@ static int check_area(struct super_block *sb, int i) | |||
632 | { | 632 | { |
633 | struct logfs_super *super = logfs_super(sb); | 633 | struct logfs_super *super = logfs_super(sb); |
634 | struct logfs_area *area = super->s_area[i]; | 634 | struct logfs_area *area = super->s_area[i]; |
635 | struct logfs_object_header oh; | 635 | gc_level_t gc_level; |
636 | u32 cleaned, valid, ec; | ||
636 | u32 segno = area->a_segno; | 637 | u32 segno = area->a_segno; |
637 | u32 ofs = area->a_used_bytes; | 638 | u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes); |
638 | __be32 crc; | ||
639 | int err; | ||
640 | 639 | ||
641 | if (!area->a_is_open) | 640 | if (!area->a_is_open) |
642 | return 0; | 641 | return 0; |
643 | 642 | ||
644 | for (ofs = area->a_used_bytes; | 643 | if (super->s_devops->can_write_buf(sb, ofs) == 0) |
645 | ofs <= super->s_segsize - sizeof(oh); | 644 | return 0; |
646 | ofs += (u32)be16_to_cpu(oh.len) + sizeof(oh)) { | ||
647 | err = wbuf_read(sb, dev_ofs(sb, segno, ofs), sizeof(oh), &oh); | ||
648 | if (err) | ||
649 | return err; | ||
650 | |||
651 | if (!memchr_inv(&oh, 0xff, sizeof(oh))) | ||
652 | break; | ||
653 | 645 | ||
654 | crc = logfs_crc32(&oh, sizeof(oh) - 4, 4); | 646 | printk(KERN_INFO"LogFS: Possibly incomplete write at %llx\n", ofs); |
655 | if (crc != oh.crc) { | 647 | /* |
656 | printk(KERN_INFO "interrupted header at %llx\n", | 648 | * The device cannot write back the write buffer. Most likely the |
657 | dev_ofs(sb, segno, ofs)); | 649 | * wbuf was already written out and the system crashed at some point |
658 | return 0; | 650 | * before the journal commit happened. In that case we wouldn't have |
659 | } | 651 | * to do anything. But if the crash happened before the wbuf was |
660 | } | 652 | * written out correctly, we must GC this segment. So assume the |
661 | if (ofs != area->a_used_bytes) { | 653 | * worst and always do the GC run. |
662 | printk(KERN_INFO "%x bytes unaccounted data found at %llx\n", | 654 | */ |
663 | ofs - area->a_used_bytes, | 655 | area->a_is_open = 0; |
664 | dev_ofs(sb, segno, area->a_used_bytes)); | 656 | valid = logfs_valid_bytes(sb, segno, &ec, &gc_level); |
665 | area->a_used_bytes = ofs; | 657 | cleaned = logfs_gc_segment(sb, segno); |
666 | } | 658 | if (cleaned != valid) |
659 | return -EIO; | ||
667 | return 0; | 660 | return 0; |
668 | } | 661 | } |
669 | 662 | ||
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 14ed27274da..755a92e8daa 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c | |||
@@ -193,6 +193,7 @@ static void logfs_init_inode(struct super_block *sb, struct inode *inode) | |||
193 | inode->i_ctime = CURRENT_TIME; | 193 | inode->i_ctime = CURRENT_TIME; |
194 | inode->i_mtime = CURRENT_TIME; | 194 | inode->i_mtime = CURRENT_TIME; |
195 | inode->i_nlink = 1; | 195 | inode->i_nlink = 1; |
196 | li->li_refcount = 1; | ||
196 | INIT_LIST_HEAD(&li->li_freeing_list); | 197 | INIT_LIST_HEAD(&li->li_freeing_list); |
197 | 198 | ||
198 | for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++) | 199 | for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++) |
@@ -326,7 +327,7 @@ static void logfs_set_ino_generation(struct super_block *sb, | |||
326 | u64 ino; | 327 | u64 ino; |
327 | 328 | ||
328 | mutex_lock(&super->s_journal_mutex); | 329 | mutex_lock(&super->s_journal_mutex); |
329 | ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino); | 330 | ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino + 1); |
330 | super->s_last_ino = ino; | 331 | super->s_last_ino = ino; |
331 | super->s_inos_till_wrap--; | 332 | super->s_inos_till_wrap--; |
332 | if (super->s_inos_till_wrap < 0) { | 333 | if (super->s_inos_till_wrap < 0) { |
@@ -386,8 +387,7 @@ static void logfs_init_once(void *_li) | |||
386 | 387 | ||
387 | static int logfs_sync_fs(struct super_block *sb, int wait) | 388 | static int logfs_sync_fs(struct super_block *sb, int wait) |
388 | { | 389 | { |
389 | /* FIXME: write anchor */ | 390 | logfs_write_anchor(sb); |
390 | logfs_super(sb)->s_devops->sync(sb); | ||
391 | return 0; | 391 | return 0; |
392 | } | 392 | } |
393 | 393 | ||
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c index fb0a613f885..4b0e0616b35 100644 --- a/fs/logfs/journal.c +++ b/fs/logfs/journal.c | |||
@@ -132,10 +132,9 @@ static int read_area(struct super_block *sb, struct logfs_je_area *a) | |||
132 | 132 | ||
133 | ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes); | 133 | ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes); |
134 | if (super->s_writesize > 1) | 134 | if (super->s_writesize > 1) |
135 | logfs_buf_recover(area, ofs, a + 1, super->s_writesize); | 135 | return logfs_buf_recover(area, ofs, a + 1, super->s_writesize); |
136 | else | 136 | else |
137 | logfs_buf_recover(area, ofs, NULL, 0); | 137 | return logfs_buf_recover(area, ofs, NULL, 0); |
138 | return 0; | ||
139 | } | 138 | } |
140 | 139 | ||
141 | static void *unpack(void *from, void *to) | 140 | static void *unpack(void *from, void *to) |
@@ -245,7 +244,7 @@ static int read_je(struct super_block *sb, u64 ofs) | |||
245 | read_erasecount(sb, unpack(jh, scratch)); | 244 | read_erasecount(sb, unpack(jh, scratch)); |
246 | break; | 245 | break; |
247 | case JE_AREA: | 246 | case JE_AREA: |
248 | read_area(sb, unpack(jh, scratch)); | 247 | err = read_area(sb, unpack(jh, scratch)); |
249 | break; | 248 | break; |
250 | case JE_OBJ_ALIAS: | 249 | case JE_OBJ_ALIAS: |
251 | err = logfs_load_object_aliases(sb, unpack(jh, scratch), | 250 | err = logfs_load_object_aliases(sb, unpack(jh, scratch), |
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 0a3df1a0c93..93b55f33724 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h | |||
@@ -144,6 +144,7 @@ struct logfs_area_ops { | |||
144 | * @erase: erase one segment | 144 | * @erase: erase one segment |
145 | * @read: read from the device | 145 | * @read: read from the device |
146 | * @erase: erase part of the device | 146 | * @erase: erase part of the device |
147 | * @can_write_buf: decide whether wbuf can be written to ofs | ||
147 | */ | 148 | */ |
148 | struct logfs_device_ops { | 149 | struct logfs_device_ops { |
149 | struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs); | 150 | struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs); |
@@ -153,6 +154,7 @@ struct logfs_device_ops { | |||
153 | void (*writeseg)(struct super_block *sb, u64 ofs, size_t len); | 154 | void (*writeseg)(struct super_block *sb, u64 ofs, size_t len); |
154 | int (*erase)(struct super_block *sb, loff_t ofs, size_t len, | 155 | int (*erase)(struct super_block *sb, loff_t ofs, size_t len, |
155 | int ensure_write); | 156 | int ensure_write); |
157 | int (*can_write_buf)(struct super_block *sb, u64 ofs); | ||
156 | void (*sync)(struct super_block *sb); | 158 | void (*sync)(struct super_block *sb); |
157 | void (*put_device)(struct super_block *sb); | 159 | void (*put_device)(struct super_block *sb); |
158 | }; | 160 | }; |
@@ -394,6 +396,7 @@ struct logfs_super { | |||
394 | int s_lock_count; | 396 | int s_lock_count; |
395 | mempool_t *s_block_pool; /* struct logfs_block pool */ | 397 | mempool_t *s_block_pool; /* struct logfs_block pool */ |
396 | mempool_t *s_shadow_pool; /* struct logfs_shadow pool */ | 398 | mempool_t *s_shadow_pool; /* struct logfs_shadow pool */ |
399 | struct list_head s_writeback_list; /* writeback pages */ | ||
397 | /* | 400 | /* |
398 | * Space accounting: | 401 | * Space accounting: |
399 | * - s_used_bytes specifies space used to store valid data objects. | 402 | * - s_used_bytes specifies space used to store valid data objects. |
@@ -598,19 +601,19 @@ void freeseg(struct super_block *sb, u32 segno); | |||
598 | int logfs_init_areas(struct super_block *sb); | 601 | int logfs_init_areas(struct super_block *sb); |
599 | void logfs_cleanup_areas(struct super_block *sb); | 602 | void logfs_cleanup_areas(struct super_block *sb); |
600 | int logfs_open_area(struct logfs_area *area, size_t bytes); | 603 | int logfs_open_area(struct logfs_area *area, size_t bytes); |
601 | void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | 604 | int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, |
602 | int use_filler); | 605 | int use_filler); |
603 | 606 | ||
604 | static inline void logfs_buf_write(struct logfs_area *area, u64 ofs, | 607 | static inline int logfs_buf_write(struct logfs_area *area, u64 ofs, |
605 | void *buf, size_t len) | 608 | void *buf, size_t len) |
606 | { | 609 | { |
607 | __logfs_buf_write(area, ofs, buf, len, 0); | 610 | return __logfs_buf_write(area, ofs, buf, len, 0); |
608 | } | 611 | } |
609 | 612 | ||
610 | static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs, | 613 | static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs, |
611 | void *buf, size_t len) | 614 | void *buf, size_t len) |
612 | { | 615 | { |
613 | __logfs_buf_write(area, ofs, buf, len, 1); | 616 | return __logfs_buf_write(area, ofs, buf, len, 1); |
614 | } | 617 | } |
615 | 618 | ||
616 | /* super.c */ | 619 | /* super.c */ |
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 3159db6958e..0718d112a1a 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c | |||
@@ -892,6 +892,8 @@ u64 logfs_seek_hole(struct inode *inode, u64 bix) | |||
892 | return bix; | 892 | return bix; |
893 | else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED) | 893 | else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED) |
894 | bix = maxbix(li->li_height); | 894 | bix = maxbix(li->li_height); |
895 | else if (bix >= maxbix(li->li_height)) | ||
896 | return bix; | ||
895 | else { | 897 | else { |
896 | bix = seek_holedata_loop(inode, bix, 0); | 898 | bix = seek_holedata_loop(inode, bix, 0); |
897 | if (bix < maxbix(li->li_height)) | 899 | if (bix < maxbix(li->li_height)) |
@@ -1093,17 +1095,25 @@ static int logfs_reserve_bytes(struct inode *inode, int bytes) | |||
1093 | int get_page_reserve(struct inode *inode, struct page *page) | 1095 | int get_page_reserve(struct inode *inode, struct page *page) |
1094 | { | 1096 | { |
1095 | struct logfs_super *super = logfs_super(inode->i_sb); | 1097 | struct logfs_super *super = logfs_super(inode->i_sb); |
1098 | struct logfs_block *block = logfs_block(page); | ||
1096 | int ret; | 1099 | int ret; |
1097 | 1100 | ||
1098 | if (logfs_block(page) && logfs_block(page)->reserved_bytes) | 1101 | if (block && block->reserved_bytes) |
1099 | return 0; | 1102 | return 0; |
1100 | 1103 | ||
1101 | logfs_get_wblocks(inode->i_sb, page, WF_LOCK); | 1104 | logfs_get_wblocks(inode->i_sb, page, WF_LOCK); |
1102 | ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE); | 1105 | while ((ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE)) && |
1106 | !list_empty(&super->s_writeback_list)) { | ||
1107 | block = list_entry(super->s_writeback_list.next, | ||
1108 | struct logfs_block, alias_list); | ||
1109 | block->ops->write_block(block); | ||
1110 | } | ||
1103 | if (!ret) { | 1111 | if (!ret) { |
1104 | alloc_data_block(inode, page); | 1112 | alloc_data_block(inode, page); |
1105 | logfs_block(page)->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE; | 1113 | block = logfs_block(page); |
1114 | block->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE; | ||
1106 | super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE; | 1115 | super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE; |
1116 | list_move_tail(&block->alias_list, &super->s_writeback_list); | ||
1107 | } | 1117 | } |
1108 | logfs_put_wblocks(inode->i_sb, page, WF_LOCK); | 1118 | logfs_put_wblocks(inode->i_sb, page, WF_LOCK); |
1109 | return ret; | 1119 | return ret; |
@@ -1861,7 +1871,7 @@ int logfs_truncate(struct inode *inode, u64 target) | |||
1861 | size = target; | 1871 | size = target; |
1862 | 1872 | ||
1863 | logfs_get_wblocks(sb, NULL, 1); | 1873 | logfs_get_wblocks(sb, NULL, 1); |
1864 | err = __logfs_truncate(inode, target); | 1874 | err = __logfs_truncate(inode, size); |
1865 | if (!err) | 1875 | if (!err) |
1866 | err = __logfs_write_inode(inode, 0); | 1876 | err = __logfs_write_inode(inode, 0); |
1867 | logfs_put_wblocks(sb, NULL, 1); | 1877 | logfs_put_wblocks(sb, NULL, 1); |
@@ -2249,6 +2259,7 @@ int logfs_init_rw(struct super_block *sb) | |||
2249 | int min_fill = 3 * super->s_no_blocks; | 2259 | int min_fill = 3 * super->s_no_blocks; |
2250 | 2260 | ||
2251 | INIT_LIST_HEAD(&super->s_object_alias); | 2261 | INIT_LIST_HEAD(&super->s_object_alias); |
2262 | INIT_LIST_HEAD(&super->s_writeback_list); | ||
2252 | mutex_init(&super->s_write_mutex); | 2263 | mutex_init(&super->s_write_mutex); |
2253 | super->s_block_pool = mempool_create_kmalloc_pool(min_fill, | 2264 | super->s_block_pool = mempool_create_kmalloc_pool(min_fill, |
2254 | sizeof(struct logfs_block)); | 2265 | sizeof(struct logfs_block)); |
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index f77ce2b470b..a9657afb70a 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c | |||
@@ -67,7 +67,7 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index, | |||
67 | return page; | 67 | return page; |
68 | } | 68 | } |
69 | 69 | ||
70 | void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | 70 | int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, |
71 | int use_filler) | 71 | int use_filler) |
72 | { | 72 | { |
73 | pgoff_t index = ofs >> PAGE_SHIFT; | 73 | 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, | |||
81 | copylen = min((ulong)len, PAGE_SIZE - offset); | 81 | copylen = min((ulong)len, PAGE_SIZE - offset); |
82 | 82 | ||
83 | page = get_mapping_page(area->a_sb, index, use_filler); | 83 | page = get_mapping_page(area->a_sb, index, use_filler); |
84 | SetPageUptodate(page); | 84 | if (IS_ERR(page)) |
85 | return PTR_ERR(page); | ||
85 | BUG_ON(!page); /* FIXME: reserve a pool */ | 86 | BUG_ON(!page); /* FIXME: reserve a pool */ |
87 | SetPageUptodate(page); | ||
86 | memcpy(page_address(page) + offset, buf, copylen); | 88 | memcpy(page_address(page) + offset, buf, copylen); |
87 | SetPagePrivate(page); | 89 | SetPagePrivate(page); |
88 | page_cache_release(page); | 90 | page_cache_release(page); |
@@ -92,6 +94,7 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | |||
92 | offset = 0; | 94 | offset = 0; |
93 | index++; | 95 | index++; |
94 | } while (len); | 96 | } while (len); |
97 | return 0; | ||
95 | } | 98 | } |
96 | 99 | ||
97 | static void pad_partial_page(struct logfs_area *area) | 100 | static void pad_partial_page(struct logfs_area *area) |
diff --git a/fs/logfs/super.c b/fs/logfs/super.c index d7c23ed8349..d651e10a1e9 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c | |||
@@ -138,10 +138,14 @@ static int logfs_sb_set(struct super_block *sb, void *_super) | |||
138 | sb->s_fs_info = super; | 138 | sb->s_fs_info = super; |
139 | sb->s_mtd = super->s_mtd; | 139 | sb->s_mtd = super->s_mtd; |
140 | sb->s_bdev = super->s_bdev; | 140 | sb->s_bdev = super->s_bdev; |
141 | #ifdef CONFIG_BLOCK | ||
141 | if (sb->s_bdev) | 142 | if (sb->s_bdev) |
142 | sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info; | 143 | sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info; |
144 | #endif | ||
145 | #ifdef CONFIG_MTD | ||
143 | if (sb->s_mtd) | 146 | if (sb->s_mtd) |
144 | sb->s_bdi = sb->s_mtd->backing_dev_info; | 147 | sb->s_bdi = sb->s_mtd->backing_dev_info; |
148 | #endif | ||
145 | return 0; | 149 | return 0; |
146 | } | 150 | } |
147 | 151 | ||
@@ -382,7 +386,7 @@ static struct page *find_super_block(struct super_block *sb) | |||
382 | if (!first || IS_ERR(first)) | 386 | if (!first || IS_ERR(first)) |
383 | return NULL; | 387 | return NULL; |
384 | last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]); | 388 | last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]); |
385 | if (!last || IS_ERR(first)) { | 389 | if (!last || IS_ERR(last)) { |
386 | page_cache_release(first); | 390 | page_cache_release(first); |
387 | return NULL; | 391 | return NULL; |
388 | } | 392 | } |
@@ -413,7 +417,7 @@ static int __logfs_read_sb(struct super_block *sb) | |||
413 | 417 | ||
414 | page = find_super_block(sb); | 418 | page = find_super_block(sb); |
415 | if (!page) | 419 | if (!page) |
416 | return -EIO; | 420 | return -EINVAL; |
417 | 421 | ||
418 | ds = page_address(page); | 422 | ds = page_address(page); |
419 | super->s_size = be64_to_cpu(ds->ds_filesystem_size); | 423 | super->s_size = be64_to_cpu(ds->ds_filesystem_size); |
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index c99c64dc5f3..c33749f95b3 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h | |||
@@ -33,7 +33,7 @@ | |||
33 | * Atomically reads the value of @v. Note that the guaranteed | 33 | * Atomically reads the value of @v. Note that the guaranteed |
34 | * useful range of an atomic_t is only 24 bits. | 34 | * useful range of an atomic_t is only 24 bits. |
35 | */ | 35 | */ |
36 | #define atomic_read(v) ((v)->counter) | 36 | #define atomic_read(v) (*(volatile int *)&(v)->counter) |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * atomic_set - set atomic variable | 39 | * atomic_set - set atomic variable |
diff --git a/include/linux/types.h b/include/linux/types.h index c42724f8c80..23d237a075e 100644 --- a/include/linux/types.h +++ b/include/linux/types.h | |||
@@ -188,12 +188,12 @@ typedef u32 phys_addr_t; | |||
188 | typedef phys_addr_t resource_size_t; | 188 | typedef phys_addr_t resource_size_t; |
189 | 189 | ||
190 | typedef struct { | 190 | typedef struct { |
191 | volatile int counter; | 191 | int counter; |
192 | } atomic_t; | 192 | } atomic_t; |
193 | 193 | ||
194 | #ifdef CONFIG_64BIT | 194 | #ifdef CONFIG_64BIT |
195 | typedef struct { | 195 | typedef struct { |
196 | volatile long counter; | 196 | long counter; |
197 | } atomic64_t; | 197 | } atomic64_t; |
198 | #endif | 198 | #endif |
199 | 199 | ||
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 42ad8ae729a..2f0f50b450a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/highmem.h> | 15 | #include <linux/highmem.h> |
16 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
17 | #include <linux/smp_lock.h> | ||
18 | #include <linux/ptrace.h> | 17 | #include <linux/ptrace.h> |
19 | #include <linux/security.h> | 18 | #include <linux/security.h> |
20 | #include <linux/signal.h> | 19 | #include <linux/signal.h> |
@@ -666,10 +665,6 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) | |||
666 | struct task_struct *child; | 665 | struct task_struct *child; |
667 | long ret; | 666 | long ret; |
668 | 667 | ||
669 | /* | ||
670 | * This lock_kernel fixes a subtle race with suid exec | ||
671 | */ | ||
672 | lock_kernel(); | ||
673 | if (request == PTRACE_TRACEME) { | 668 | if (request == PTRACE_TRACEME) { |
674 | ret = ptrace_traceme(); | 669 | ret = ptrace_traceme(); |
675 | if (!ret) | 670 | if (!ret) |
@@ -703,7 +698,6 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) | |||
703 | out_put_task_struct: | 698 | out_put_task_struct: |
704 | put_task_struct(child); | 699 | put_task_struct(child); |
705 | out: | 700 | out: |
706 | unlock_kernel(); | ||
707 | return ret; | 701 | return ret; |
708 | } | 702 | } |
709 | 703 | ||
@@ -813,10 +807,6 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, | |||
813 | struct task_struct *child; | 807 | struct task_struct *child; |
814 | long ret; | 808 | long ret; |
815 | 809 | ||
816 | /* | ||
817 | * This lock_kernel fixes a subtle race with suid exec | ||
818 | */ | ||
819 | lock_kernel(); | ||
820 | if (request == PTRACE_TRACEME) { | 810 | if (request == PTRACE_TRACEME) { |
821 | ret = ptrace_traceme(); | 811 | ret = ptrace_traceme(); |
822 | goto out; | 812 | goto out; |
@@ -846,7 +836,6 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, | |||
846 | out_put_task_struct: | 836 | out_put_task_struct: |
847 | put_task_struct(child); | 837 | put_task_struct(child); |
848 | out: | 838 | out: |
849 | unlock_kernel(); | ||
850 | return ret; | 839 | return ret; |
851 | } | 840 | } |
852 | #endif /* CONFIG_COMPAT */ | 841 | #endif /* CONFIG_COMPAT */ |