diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-01-12 05:32:03 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-01-12 05:32:03 -0500 |
| commit | e3ee1e123183ca9847e74b7b8e2694c9e3b817a6 (patch) | |
| tree | 652a84674ed05eaa46a813de2223af0bd0168a5a /fs/buffer.c | |
| parent | 5762ba1873b0bb9faa631aaa02f533c2b9837f82 (diff) | |
| parent | c59765042f53a79a7a65585042ff463b69cb248c (diff) | |
Merge commit 'v2.6.29-rc1' into timers/hrtimers
Conflicts:
kernel/time/tick-common.c
Diffstat (limited to 'fs/buffer.c')
| -rw-r--r-- | fs/buffer.c | 98 |
1 files changed, 82 insertions, 16 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 10179cfa1152..b6e8b8632e2f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -99,10 +99,18 @@ __clear_page_buffers(struct page *page) | |||
| 99 | page_cache_release(page); | 99 | page_cache_release(page); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | |||
| 103 | static int quiet_error(struct buffer_head *bh) | ||
| 104 | { | ||
| 105 | if (!test_bit(BH_Quiet, &bh->b_state) && printk_ratelimit()) | ||
| 106 | return 0; | ||
| 107 | return 1; | ||
| 108 | } | ||
| 109 | |||
| 110 | |||
| 102 | static void buffer_io_error(struct buffer_head *bh) | 111 | static void buffer_io_error(struct buffer_head *bh) |
| 103 | { | 112 | { |
| 104 | char b[BDEVNAME_SIZE]; | 113 | char b[BDEVNAME_SIZE]; |
| 105 | |||
| 106 | printk(KERN_ERR "Buffer I/O error on device %s, logical block %Lu\n", | 114 | printk(KERN_ERR "Buffer I/O error on device %s, logical block %Lu\n", |
| 107 | bdevname(bh->b_bdev, b), | 115 | bdevname(bh->b_bdev, b), |
| 108 | (unsigned long long)bh->b_blocknr); | 116 | (unsigned long long)bh->b_blocknr); |
| @@ -144,7 +152,7 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate) | |||
| 144 | if (uptodate) { | 152 | if (uptodate) { |
| 145 | set_buffer_uptodate(bh); | 153 | set_buffer_uptodate(bh); |
| 146 | } else { | 154 | } else { |
| 147 | if (!buffer_eopnotsupp(bh) && printk_ratelimit()) { | 155 | if (!buffer_eopnotsupp(bh) && !quiet_error(bh)) { |
| 148 | buffer_io_error(bh); | 156 | buffer_io_error(bh); |
| 149 | printk(KERN_WARNING "lost page write due to " | 157 | printk(KERN_WARNING "lost page write due to " |
| 150 | "I/O error on %s\n", | 158 | "I/O error on %s\n", |
| @@ -195,10 +203,25 @@ int fsync_bdev(struct block_device *bdev) | |||
| 195 | * happen on bdev until thaw_bdev() is called. | 203 | * happen on bdev until thaw_bdev() is called. |
| 196 | * If a superblock is found on this device, we take the s_umount semaphore | 204 | * If a superblock is found on this device, we take the s_umount semaphore |
| 197 | * on it to make sure nobody unmounts until the snapshot creation is done. | 205 | * on it to make sure nobody unmounts until the snapshot creation is done. |
| 206 | * The reference counter (bd_fsfreeze_count) guarantees that only the last | ||
| 207 | * unfreeze process can unfreeze the frozen filesystem actually when multiple | ||
| 208 | * freeze requests arrive simultaneously. It counts up in freeze_bdev() and | ||
| 209 | * count down in thaw_bdev(). When it becomes 0, thaw_bdev() will unfreeze | ||
| 210 | * actually. | ||
| 198 | */ | 211 | */ |
| 199 | struct super_block *freeze_bdev(struct block_device *bdev) | 212 | struct super_block *freeze_bdev(struct block_device *bdev) |
| 200 | { | 213 | { |
| 201 | struct super_block *sb; | 214 | struct super_block *sb; |
| 215 | int error = 0; | ||
| 216 | |||
| 217 | mutex_lock(&bdev->bd_fsfreeze_mutex); | ||
| 218 | if (bdev->bd_fsfreeze_count > 0) { | ||
| 219 | bdev->bd_fsfreeze_count++; | ||
| 220 | sb = get_super(bdev); | ||
| 221 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
| 222 | return sb; | ||
| 223 | } | ||
| 224 | bdev->bd_fsfreeze_count++; | ||
| 202 | 225 | ||
| 203 | down(&bdev->bd_mount_sem); | 226 | down(&bdev->bd_mount_sem); |
| 204 | sb = get_super(bdev); | 227 | sb = get_super(bdev); |
| @@ -213,11 +236,24 @@ struct super_block *freeze_bdev(struct block_device *bdev) | |||
| 213 | 236 | ||
| 214 | sync_blockdev(sb->s_bdev); | 237 | sync_blockdev(sb->s_bdev); |
| 215 | 238 | ||
| 216 | if (sb->s_op->write_super_lockfs) | 239 | if (sb->s_op->freeze_fs) { |
| 217 | sb->s_op->write_super_lockfs(sb); | 240 | error = sb->s_op->freeze_fs(sb); |
| 241 | if (error) { | ||
| 242 | printk(KERN_ERR | ||
| 243 | "VFS:Filesystem freeze failed\n"); | ||
| 244 | sb->s_frozen = SB_UNFROZEN; | ||
| 245 | drop_super(sb); | ||
| 246 | up(&bdev->bd_mount_sem); | ||
| 247 | bdev->bd_fsfreeze_count--; | ||
| 248 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
| 249 | return ERR_PTR(error); | ||
| 250 | } | ||
| 251 | } | ||
| 218 | } | 252 | } |
| 219 | 253 | ||
| 220 | sync_blockdev(bdev); | 254 | sync_blockdev(bdev); |
| 255 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
| 256 | |||
| 221 | return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */ | 257 | return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */ |
| 222 | } | 258 | } |
| 223 | EXPORT_SYMBOL(freeze_bdev); | 259 | EXPORT_SYMBOL(freeze_bdev); |
| @@ -229,20 +265,48 @@ EXPORT_SYMBOL(freeze_bdev); | |||
| 229 | * | 265 | * |
| 230 | * Unlocks the filesystem and marks it writeable again after freeze_bdev(). | 266 | * Unlocks the filesystem and marks it writeable again after freeze_bdev(). |
| 231 | */ | 267 | */ |
| 232 | void thaw_bdev(struct block_device *bdev, struct super_block *sb) | 268 | int thaw_bdev(struct block_device *bdev, struct super_block *sb) |
| 233 | { | 269 | { |
| 270 | int error = 0; | ||
| 271 | |||
| 272 | mutex_lock(&bdev->bd_fsfreeze_mutex); | ||
| 273 | if (!bdev->bd_fsfreeze_count) { | ||
| 274 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
| 275 | return -EINVAL; | ||
| 276 | } | ||
| 277 | |||
| 278 | bdev->bd_fsfreeze_count--; | ||
| 279 | if (bdev->bd_fsfreeze_count > 0) { | ||
| 280 | if (sb) | ||
| 281 | drop_super(sb); | ||
| 282 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 234 | if (sb) { | 286 | if (sb) { |
| 235 | BUG_ON(sb->s_bdev != bdev); | 287 | BUG_ON(sb->s_bdev != bdev); |
| 236 | 288 | if (!(sb->s_flags & MS_RDONLY)) { | |
| 237 | if (sb->s_op->unlockfs) | 289 | if (sb->s_op->unfreeze_fs) { |
| 238 | sb->s_op->unlockfs(sb); | 290 | error = sb->s_op->unfreeze_fs(sb); |
| 239 | sb->s_frozen = SB_UNFROZEN; | 291 | if (error) { |
| 240 | smp_wmb(); | 292 | printk(KERN_ERR |
| 241 | wake_up(&sb->s_wait_unfrozen); | 293 | "VFS:Filesystem thaw failed\n"); |
| 294 | sb->s_frozen = SB_FREEZE_TRANS; | ||
| 295 | bdev->bd_fsfreeze_count++; | ||
| 296 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
| 297 | return error; | ||
| 298 | } | ||
| 299 | } | ||
| 300 | sb->s_frozen = SB_UNFROZEN; | ||
| 301 | smp_wmb(); | ||
| 302 | wake_up(&sb->s_wait_unfrozen); | ||
| 303 | } | ||
| 242 | drop_super(sb); | 304 | drop_super(sb); |
| 243 | } | 305 | } |
| 244 | 306 | ||
| 245 | up(&bdev->bd_mount_sem); | 307 | up(&bdev->bd_mount_sem); |
| 308 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
| 309 | return 0; | ||
| 246 | } | 310 | } |
| 247 | EXPORT_SYMBOL(thaw_bdev); | 311 | EXPORT_SYMBOL(thaw_bdev); |
| 248 | 312 | ||
| @@ -394,7 +458,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
| 394 | set_buffer_uptodate(bh); | 458 | set_buffer_uptodate(bh); |
| 395 | } else { | 459 | } else { |
| 396 | clear_buffer_uptodate(bh); | 460 | clear_buffer_uptodate(bh); |
| 397 | if (printk_ratelimit()) | 461 | if (!quiet_error(bh)) |
| 398 | buffer_io_error(bh); | 462 | buffer_io_error(bh); |
| 399 | SetPageError(page); | 463 | SetPageError(page); |
| 400 | } | 464 | } |
| @@ -455,7 +519,7 @@ static void end_buffer_async_write(struct buffer_head *bh, int uptodate) | |||
| 455 | if (uptodate) { | 519 | if (uptodate) { |
| 456 | set_buffer_uptodate(bh); | 520 | set_buffer_uptodate(bh); |
| 457 | } else { | 521 | } else { |
| 458 | if (printk_ratelimit()) { | 522 | if (!quiet_error(bh)) { |
| 459 | buffer_io_error(bh); | 523 | buffer_io_error(bh); |
| 460 | printk(KERN_WARNING "lost page write due to " | 524 | printk(KERN_WARNING "lost page write due to " |
| 461 | "I/O error on %s\n", | 525 | "I/O error on %s\n", |
| @@ -1988,7 +2052,7 @@ int block_write_begin(struct file *file, struct address_space *mapping, | |||
| 1988 | page = *pagep; | 2052 | page = *pagep; |
| 1989 | if (page == NULL) { | 2053 | if (page == NULL) { |
| 1990 | ownpage = 1; | 2054 | ownpage = 1; |
| 1991 | page = __grab_cache_page(mapping, index); | 2055 | page = grab_cache_page_write_begin(mapping, index, flags); |
| 1992 | if (!page) { | 2056 | if (!page) { |
| 1993 | status = -ENOMEM; | 2057 | status = -ENOMEM; |
| 1994 | goto out; | 2058 | goto out; |
| @@ -2014,7 +2078,6 @@ int block_write_begin(struct file *file, struct address_space *mapping, | |||
| 2014 | if (pos + len > inode->i_size) | 2078 | if (pos + len > inode->i_size) |
| 2015 | vmtruncate(inode, inode->i_size); | 2079 | vmtruncate(inode, inode->i_size); |
| 2016 | } | 2080 | } |
| 2017 | goto out; | ||
| 2018 | } | 2081 | } |
| 2019 | 2082 | ||
| 2020 | out: | 2083 | out: |
| @@ -2494,7 +2557,7 @@ int nobh_write_begin(struct file *file, struct address_space *mapping, | |||
| 2494 | from = pos & (PAGE_CACHE_SIZE - 1); | 2557 | from = pos & (PAGE_CACHE_SIZE - 1); |
| 2495 | to = from + len; | 2558 | to = from + len; |
| 2496 | 2559 | ||
| 2497 | page = __grab_cache_page(mapping, index); | 2560 | page = grab_cache_page_write_begin(mapping, index, flags); |
| 2498 | if (!page) | 2561 | if (!page) |
| 2499 | return -ENOMEM; | 2562 | return -ENOMEM; |
| 2500 | *pagep = page; | 2563 | *pagep = page; |
| @@ -2913,6 +2976,9 @@ static void end_bio_bh_io_sync(struct bio *bio, int err) | |||
| 2913 | set_bit(BH_Eopnotsupp, &bh->b_state); | 2976 | set_bit(BH_Eopnotsupp, &bh->b_state); |
| 2914 | } | 2977 | } |
| 2915 | 2978 | ||
| 2979 | if (unlikely (test_bit(BIO_QUIET,&bio->bi_flags))) | ||
| 2980 | set_bit(BH_Quiet, &bh->b_state); | ||
| 2981 | |||
| 2916 | bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags)); | 2982 | bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags)); |
| 2917 | bio_put(bio); | 2983 | bio_put(bio); |
| 2918 | } | 2984 | } |
