diff options
Diffstat (limited to 'fs')
59 files changed, 443 insertions, 182 deletions
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 5c5bc8480070..f8b86e92cd66 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
| @@ -238,6 +238,13 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, | |||
| 238 | return ERR_PTR(-ENOMEM); | 238 | return ERR_PTR(-ENOMEM); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY); | ||
| 242 | if (rc) { | ||
| 243 | __putname(v9ses->aname); | ||
| 244 | __putname(v9ses->uname); | ||
| 245 | return ERR_PTR(rc); | ||
| 246 | } | ||
| 247 | |||
| 241 | spin_lock(&v9fs_sessionlist_lock); | 248 | spin_lock(&v9fs_sessionlist_lock); |
| 242 | list_add(&v9ses->slist, &v9fs_sessionlist); | 249 | list_add(&v9ses->slist, &v9fs_sessionlist); |
| 243 | spin_unlock(&v9fs_sessionlist_lock); | 250 | spin_unlock(&v9fs_sessionlist_lock); |
| @@ -301,6 +308,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, | |||
| 301 | return fid; | 308 | return fid; |
| 302 | 309 | ||
| 303 | error: | 310 | error: |
| 311 | bdi_destroy(&v9ses->bdi); | ||
| 304 | return ERR_PTR(retval); | 312 | return ERR_PTR(retval); |
| 305 | } | 313 | } |
| 306 | 314 | ||
| @@ -326,6 +334,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) | |||
| 326 | __putname(v9ses->uname); | 334 | __putname(v9ses->uname); |
| 327 | __putname(v9ses->aname); | 335 | __putname(v9ses->aname); |
| 328 | 336 | ||
| 337 | bdi_destroy(&v9ses->bdi); | ||
| 338 | |||
| 329 | spin_lock(&v9fs_sessionlist_lock); | 339 | spin_lock(&v9fs_sessionlist_lock); |
| 330 | list_del(&v9ses->slist); | 340 | list_del(&v9ses->slist); |
| 331 | spin_unlock(&v9fs_sessionlist_lock); | 341 | spin_unlock(&v9fs_sessionlist_lock); |
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index a0a8d3dd1361..bec4d0bcb458 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | * Boston, MA 02111-1301 USA | 20 | * Boston, MA 02111-1301 USA |
| 21 | * | 21 | * |
| 22 | */ | 22 | */ |
| 23 | #include <linux/backing-dev.h> | ||
| 23 | 24 | ||
| 24 | /** | 25 | /** |
| 25 | * enum p9_session_flags - option flags for each 9P session | 26 | * enum p9_session_flags - option flags for each 9P session |
| @@ -102,6 +103,7 @@ struct v9fs_session_info { | |||
| 102 | u32 uid; /* if ACCESS_SINGLE, the uid that has access */ | 103 | u32 uid; /* if ACCESS_SINGLE, the uid that has access */ |
| 103 | struct p9_client *clnt; /* 9p client */ | 104 | struct p9_client *clnt; /* 9p client */ |
| 104 | struct list_head slist; /* list of sessions registered with v9fs */ | 105 | struct list_head slist; /* list of sessions registered with v9fs */ |
| 106 | struct backing_dev_info bdi; | ||
| 105 | }; | 107 | }; |
| 106 | 108 | ||
| 107 | struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, | 109 | struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 491108bd6e0d..806da5d3b3a0 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
| @@ -77,6 +77,7 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, | |||
| 77 | sb->s_blocksize = 1 << sb->s_blocksize_bits; | 77 | sb->s_blocksize = 1 << sb->s_blocksize_bits; |
| 78 | sb->s_magic = V9FS_MAGIC; | 78 | sb->s_magic = V9FS_MAGIC; |
| 79 | sb->s_op = &v9fs_super_ops; | 79 | sb->s_op = &v9fs_super_ops; |
| 80 | sb->s_bdi = &v9ses->bdi; | ||
| 80 | 81 | ||
| 81 | sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | | 82 | sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | |
| 82 | MS_NOATIME; | 83 | MS_NOATIME; |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index c54dad4e6063..a10f2582844f 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
| 20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 21 | #include <linux/fscache.h> | 21 | #include <linux/fscache.h> |
| 22 | #include <linux/backing-dev.h> | ||
| 22 | 23 | ||
| 23 | #include "afs.h" | 24 | #include "afs.h" |
| 24 | #include "afs_vl.h" | 25 | #include "afs_vl.h" |
| @@ -313,6 +314,7 @@ struct afs_volume { | |||
| 313 | unsigned short rjservers; /* number of servers discarded due to -ENOMEDIUM */ | 314 | unsigned short rjservers; /* number of servers discarded due to -ENOMEDIUM */ |
| 314 | struct afs_server *servers[8]; /* servers on which volume resides (ordered) */ | 315 | struct afs_server *servers[8]; /* servers on which volume resides (ordered) */ |
| 315 | struct rw_semaphore server_sem; /* lock for accessing current server */ | 316 | struct rw_semaphore server_sem; /* lock for accessing current server */ |
| 317 | struct backing_dev_info bdi; | ||
| 316 | }; | 318 | }; |
| 317 | 319 | ||
| 318 | /* | 320 | /* |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 14f6431598ad..e932e5a3a0c1 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
| @@ -311,6 +311,7 @@ static int afs_fill_super(struct super_block *sb, void *data) | |||
| 311 | sb->s_magic = AFS_FS_MAGIC; | 311 | sb->s_magic = AFS_FS_MAGIC; |
| 312 | sb->s_op = &afs_super_ops; | 312 | sb->s_op = &afs_super_ops; |
| 313 | sb->s_fs_info = as; | 313 | sb->s_fs_info = as; |
| 314 | sb->s_bdi = &as->volume->bdi; | ||
| 314 | 315 | ||
| 315 | /* allocate the root inode and dentry */ | 316 | /* allocate the root inode and dentry */ |
| 316 | fid.vid = as->volume->vid; | 317 | fid.vid = as->volume->vid; |
diff --git a/fs/afs/volume.c b/fs/afs/volume.c index a353e69e2391..401eeb21869f 100644 --- a/fs/afs/volume.c +++ b/fs/afs/volume.c | |||
| @@ -106,6 +106,10 @@ struct afs_volume *afs_volume_lookup(struct afs_mount_params *params) | |||
| 106 | volume->cell = params->cell; | 106 | volume->cell = params->cell; |
| 107 | volume->vid = vlocation->vldb.vid[params->type]; | 107 | volume->vid = vlocation->vldb.vid[params->type]; |
| 108 | 108 | ||
| 109 | ret = bdi_setup_and_register(&volume->bdi, "afs", BDI_CAP_MAP_COPY); | ||
| 110 | if (ret) | ||
| 111 | goto error_bdi; | ||
| 112 | |||
| 109 | init_rwsem(&volume->server_sem); | 113 | init_rwsem(&volume->server_sem); |
| 110 | 114 | ||
| 111 | /* look up all the applicable server records */ | 115 | /* look up all the applicable server records */ |
| @@ -151,6 +155,8 @@ error: | |||
| 151 | return ERR_PTR(ret); | 155 | return ERR_PTR(ret); |
| 152 | 156 | ||
| 153 | error_discard: | 157 | error_discard: |
| 158 | bdi_destroy(&volume->bdi); | ||
| 159 | error_bdi: | ||
| 154 | up_write(¶ms->cell->vl_sem); | 160 | up_write(¶ms->cell->vl_sem); |
| 155 | 161 | ||
| 156 | for (loop = volume->nservers - 1; loop >= 0; loop--) | 162 | for (loop = volume->nservers - 1; loop >= 0; loop--) |
| @@ -200,6 +206,7 @@ void afs_put_volume(struct afs_volume *volume) | |||
| 200 | for (loop = volume->nservers - 1; loop >= 0; loop--) | 206 | for (loop = volume->nservers - 1; loop >= 0; loop--) |
| 201 | afs_put_server(volume->servers[loop]); | 207 | afs_put_server(volume->servers[loop]); |
| 202 | 208 | ||
| 209 | bdi_destroy(&volume->bdi); | ||
| 203 | kfree(volume); | 210 | kfree(volume); |
| 204 | 211 | ||
| 205 | _leave(" [destroyed]"); | 212 | _leave(" [destroyed]"); |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 7ab23e006e4c..2c5f9a0e5d72 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
| @@ -1005,15 +1005,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux( | |||
| 1005 | } | 1005 | } |
| 1006 | } else if (!mm->start_data) { | 1006 | } else if (!mm->start_data) { |
| 1007 | mm->start_data = seg->addr; | 1007 | mm->start_data = seg->addr; |
| 1008 | #ifndef CONFIG_MMU | ||
| 1009 | mm->end_data = seg->addr + phdr->p_memsz; | 1008 | mm->end_data = seg->addr + phdr->p_memsz; |
| 1010 | #endif | ||
| 1011 | } | 1009 | } |
| 1012 | |||
| 1013 | #ifdef CONFIG_MMU | ||
| 1014 | if (seg->addr + phdr->p_memsz > mm->end_data) | ||
| 1015 | mm->end_data = seg->addr + phdr->p_memsz; | ||
| 1016 | #endif | ||
| 1017 | } | 1010 | } |
| 1018 | 1011 | ||
| 1019 | seg++; | 1012 | seg++; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 2a6d0193f139..6dcee88c2e5d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -406,16 +406,23 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin) | |||
| 406 | 406 | ||
| 407 | int blkdev_fsync(struct file *filp, struct dentry *dentry, int datasync) | 407 | int blkdev_fsync(struct file *filp, struct dentry *dentry, int datasync) |
| 408 | { | 408 | { |
| 409 | struct block_device *bdev = I_BDEV(filp->f_mapping->host); | 409 | struct inode *bd_inode = filp->f_mapping->host; |
| 410 | struct block_device *bdev = I_BDEV(bd_inode); | ||
| 410 | int error; | 411 | int error; |
| 411 | 412 | ||
| 412 | error = sync_blockdev(bdev); | 413 | /* |
| 413 | if (error) | 414 | * There is no need to serialise calls to blkdev_issue_flush with |
| 414 | return error; | 415 | * i_mutex and doing so causes performance issues with concurrent |
| 415 | 416 | * O_SYNC writers to a block device. | |
| 417 | */ | ||
| 418 | mutex_unlock(&bd_inode->i_mutex); | ||
| 419 | |||
| 416 | error = blkdev_issue_flush(bdev, NULL); | 420 | error = blkdev_issue_flush(bdev, NULL); |
| 417 | if (error == -EOPNOTSUPP) | 421 | if (error == -EOPNOTSUPP) |
| 418 | error = 0; | 422 | error = 0; |
| 423 | |||
| 424 | mutex_lock(&bd_inode->i_mutex); | ||
| 425 | |||
| 419 | return error; | 426 | return error; |
| 420 | } | 427 | } |
| 421 | EXPORT_SYMBOL(blkdev_fsync); | 428 | EXPORT_SYMBOL(blkdev_fsync); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e7b8f2c89ccb..feca04197d02 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -44,8 +44,6 @@ static struct extent_io_ops btree_extent_io_ops; | |||
| 44 | static void end_workqueue_fn(struct btrfs_work *work); | 44 | static void end_workqueue_fn(struct btrfs_work *work); |
| 45 | static void free_fs_root(struct btrfs_root *root); | 45 | static void free_fs_root(struct btrfs_root *root); |
| 46 | 46 | ||
| 47 | static atomic_t btrfs_bdi_num = ATOMIC_INIT(0); | ||
| 48 | |||
| 49 | /* | 47 | /* |
| 50 | * end_io_wq structs are used to do processing in task context when an IO is | 48 | * end_io_wq structs are used to do processing in task context when an IO is |
| 51 | * complete. This is used during reads to verify checksums, and it is used | 49 | * complete. This is used during reads to verify checksums, and it is used |
| @@ -1375,19 +1373,11 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) | |||
| 1375 | { | 1373 | { |
| 1376 | int err; | 1374 | int err; |
| 1377 | 1375 | ||
| 1378 | bdi->name = "btrfs"; | ||
| 1379 | bdi->capabilities = BDI_CAP_MAP_COPY; | 1376 | bdi->capabilities = BDI_CAP_MAP_COPY; |
| 1380 | err = bdi_init(bdi); | 1377 | err = bdi_setup_and_register(bdi, "btrfs", BDI_CAP_MAP_COPY); |
| 1381 | if (err) | 1378 | if (err) |
| 1382 | return err; | 1379 | return err; |
| 1383 | 1380 | ||
| 1384 | err = bdi_register(bdi, NULL, "btrfs-%d", | ||
| 1385 | atomic_inc_return(&btrfs_bdi_num)); | ||
| 1386 | if (err) { | ||
| 1387 | bdi_destroy(bdi); | ||
| 1388 | return err; | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | bdi->ra_pages = default_backing_dev_info.ra_pages; | 1381 | bdi->ra_pages = default_backing_dev_info.ra_pages; |
| 1392 | bdi->unplug_io_fn = btrfs_unplug_io_fn; | 1382 | bdi->unplug_io_fn = btrfs_unplug_io_fn; |
| 1393 | bdi->unplug_io_data = info; | 1383 | bdi->unplug_io_data = info; |
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 412593703d1e..4b42c2bb603f 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
| @@ -509,7 +509,7 @@ static void writepages_finish(struct ceph_osd_request *req, | |||
| 509 | u64 bytes = 0; | 509 | u64 bytes = 0; |
| 510 | struct ceph_client *client = ceph_inode_to_client(inode); | 510 | struct ceph_client *client = ceph_inode_to_client(inode); |
| 511 | long writeback_stat; | 511 | long writeback_stat; |
| 512 | unsigned issued = __ceph_caps_issued(ci, NULL); | 512 | unsigned issued = ceph_caps_issued(ci); |
| 513 | 513 | ||
| 514 | /* parse reply */ | 514 | /* parse reply */ |
| 515 | replyhead = msg->front.iov_base; | 515 | replyhead = msg->front.iov_base; |
diff --git a/fs/ceph/auth.c b/fs/ceph/auth.c index f6394b94b866..818afe72e6c7 100644 --- a/fs/ceph/auth.c +++ b/fs/ceph/auth.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <linux/module.h> | 3 | #include <linux/module.h> |
| 4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
| 5 | #include <linux/err.h> | 5 | #include <linux/err.h> |
| 6 | #include <linux/slab.h> | ||
| 6 | 7 | ||
| 7 | #include "types.h" | 8 | #include "types.h" |
| 8 | #include "auth_none.h" | 9 | #include "auth_none.h" |
diff --git a/fs/ceph/auth_none.h b/fs/ceph/auth_none.h index 56c05533a31c..8164df1a08be 100644 --- a/fs/ceph/auth_none.h +++ b/fs/ceph/auth_none.h | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #ifndef _FS_CEPH_AUTH_NONE_H | 1 | #ifndef _FS_CEPH_AUTH_NONE_H |
| 2 | #define _FS_CEPH_AUTH_NONE_H | 2 | #define _FS_CEPH_AUTH_NONE_H |
| 3 | 3 | ||
| 4 | #include <linux/slab.h> | ||
| 5 | |||
| 4 | #include "auth.h" | 6 | #include "auth.h" |
| 5 | 7 | ||
| 6 | /* | 8 | /* |
diff --git a/fs/ceph/auth_x.c b/fs/ceph/auth_x.c index d9001a4dc8cc..fee5a08da881 100644 --- a/fs/ceph/auth_x.c +++ b/fs/ceph/auth_x.c | |||
| @@ -12,8 +12,6 @@ | |||
| 12 | #include "auth.h" | 12 | #include "auth.h" |
| 13 | #include "decode.h" | 13 | #include "decode.h" |
| 14 | 14 | ||
| 15 | struct kmem_cache *ceph_x_ticketbuf_cachep; | ||
| 16 | |||
| 17 | #define TEMP_TICKET_BUF_LEN 256 | 15 | #define TEMP_TICKET_BUF_LEN 256 |
| 18 | 16 | ||
| 19 | static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); | 17 | static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); |
| @@ -131,13 +129,12 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, | |||
| 131 | char *ticket_buf; | 129 | char *ticket_buf; |
| 132 | u8 struct_v; | 130 | u8 struct_v; |
| 133 | 131 | ||
| 134 | dbuf = kmem_cache_alloc(ceph_x_ticketbuf_cachep, GFP_NOFS | GFP_ATOMIC); | 132 | dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); |
| 135 | if (!dbuf) | 133 | if (!dbuf) |
| 136 | return -ENOMEM; | 134 | return -ENOMEM; |
| 137 | 135 | ||
| 138 | ret = -ENOMEM; | 136 | ret = -ENOMEM; |
| 139 | ticket_buf = kmem_cache_alloc(ceph_x_ticketbuf_cachep, | 137 | ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); |
| 140 | GFP_NOFS | GFP_ATOMIC); | ||
| 141 | if (!ticket_buf) | 138 | if (!ticket_buf) |
| 142 | goto out_dbuf; | 139 | goto out_dbuf; |
| 143 | 140 | ||
| @@ -251,9 +248,9 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, | |||
| 251 | 248 | ||
| 252 | ret = 0; | 249 | ret = 0; |
| 253 | out: | 250 | out: |
| 254 | kmem_cache_free(ceph_x_ticketbuf_cachep, ticket_buf); | 251 | kfree(ticket_buf); |
| 255 | out_dbuf: | 252 | out_dbuf: |
| 256 | kmem_cache_free(ceph_x_ticketbuf_cachep, dbuf); | 253 | kfree(dbuf); |
| 257 | return ret; | 254 | return ret; |
| 258 | 255 | ||
| 259 | bad: | 256 | bad: |
| @@ -605,8 +602,6 @@ static void ceph_x_destroy(struct ceph_auth_client *ac) | |||
| 605 | remove_ticket_handler(ac, th); | 602 | remove_ticket_handler(ac, th); |
| 606 | } | 603 | } |
| 607 | 604 | ||
| 608 | kmem_cache_destroy(ceph_x_ticketbuf_cachep); | ||
| 609 | |||
| 610 | kfree(ac->private); | 605 | kfree(ac->private); |
| 611 | ac->private = NULL; | 606 | ac->private = NULL; |
| 612 | } | 607 | } |
| @@ -641,26 +636,20 @@ int ceph_x_init(struct ceph_auth_client *ac) | |||
| 641 | int ret; | 636 | int ret; |
| 642 | 637 | ||
| 643 | dout("ceph_x_init %p\n", ac); | 638 | dout("ceph_x_init %p\n", ac); |
| 639 | ret = -ENOMEM; | ||
| 644 | xi = kzalloc(sizeof(*xi), GFP_NOFS); | 640 | xi = kzalloc(sizeof(*xi), GFP_NOFS); |
| 645 | if (!xi) | 641 | if (!xi) |
| 646 | return -ENOMEM; | 642 | goto out; |
| 647 | 643 | ||
| 648 | ret = -ENOMEM; | ||
| 649 | ceph_x_ticketbuf_cachep = kmem_cache_create("ceph_x_ticketbuf", | ||
| 650 | TEMP_TICKET_BUF_LEN, 8, | ||
| 651 | (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), | ||
| 652 | NULL); | ||
| 653 | if (!ceph_x_ticketbuf_cachep) | ||
| 654 | goto done_nomem; | ||
| 655 | ret = -EINVAL; | 644 | ret = -EINVAL; |
| 656 | if (!ac->secret) { | 645 | if (!ac->secret) { |
| 657 | pr_err("no secret set (for auth_x protocol)\n"); | 646 | pr_err("no secret set (for auth_x protocol)\n"); |
| 658 | goto done_nomem; | 647 | goto out_nomem; |
| 659 | } | 648 | } |
| 660 | 649 | ||
| 661 | ret = ceph_crypto_key_unarmor(&xi->secret, ac->secret); | 650 | ret = ceph_crypto_key_unarmor(&xi->secret, ac->secret); |
| 662 | if (ret) | 651 | if (ret) |
| 663 | goto done_nomem; | 652 | goto out_nomem; |
| 664 | 653 | ||
| 665 | xi->starting = true; | 654 | xi->starting = true; |
| 666 | xi->ticket_handlers = RB_ROOT; | 655 | xi->ticket_handlers = RB_ROOT; |
| @@ -670,10 +659,9 @@ int ceph_x_init(struct ceph_auth_client *ac) | |||
| 670 | ac->ops = &ceph_x_ops; | 659 | ac->ops = &ceph_x_ops; |
| 671 | return 0; | 660 | return 0; |
| 672 | 661 | ||
| 673 | done_nomem: | 662 | out_nomem: |
| 674 | kfree(xi); | 663 | kfree(xi); |
| 675 | if (ceph_x_ticketbuf_cachep) | 664 | out: |
| 676 | kmem_cache_destroy(ceph_x_ticketbuf_cachep); | ||
| 677 | return ret; | 665 | return ret; |
| 678 | } | 666 | } |
| 679 | 667 | ||
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index aa2239fa9a3b..0c1681806867 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
| @@ -1861,8 +1861,8 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc, | |||
| 1861 | } else { | 1861 | } else { |
| 1862 | pr_err("%p auth cap %p not mds%d ???\n", inode, | 1862 | pr_err("%p auth cap %p not mds%d ???\n", inode, |
| 1863 | cap, session->s_mds); | 1863 | cap, session->s_mds); |
| 1864 | spin_unlock(&inode->i_lock); | ||
| 1865 | } | 1864 | } |
| 1865 | spin_unlock(&inode->i_lock); | ||
| 1866 | } | 1866 | } |
| 1867 | } | 1867 | } |
| 1868 | 1868 | ||
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index ea8ee2e526aa..650d2db5ed26 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
| @@ -880,7 +880,16 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 880 | * do_request, above). If there is no trace, we need | 880 | * do_request, above). If there is no trace, we need |
| 881 | * to do it here. | 881 | * to do it here. |
| 882 | */ | 882 | */ |
| 883 | |||
| 884 | /* d_move screws up d_subdirs order */ | ||
| 885 | ceph_i_clear(new_dir, CEPH_I_COMPLETE); | ||
| 886 | |||
| 883 | d_move(old_dentry, new_dentry); | 887 | d_move(old_dentry, new_dentry); |
| 888 | |||
| 889 | /* ensure target dentry is invalidated, despite | ||
| 890 | rehashing bug in vfs_rename_dir */ | ||
| 891 | new_dentry->d_time = jiffies; | ||
| 892 | ceph_dentry(new_dentry)->lease_shared_gen = 0; | ||
| 884 | } | 893 | } |
| 885 | ceph_mdsc_put_request(req); | 894 | ceph_mdsc_put_request(req); |
| 886 | return err; | 895 | return err; |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 4add3d5da2c1..ed6f19721d6e 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
| @@ -665,7 +665,8 @@ more: | |||
| 665 | * throw out any page cache pages in this range. this | 665 | * throw out any page cache pages in this range. this |
| 666 | * may block. | 666 | * may block. |
| 667 | */ | 667 | */ |
| 668 | truncate_inode_pages_range(inode->i_mapping, pos, pos+len); | 668 | truncate_inode_pages_range(inode->i_mapping, pos, |
| 669 | (pos+len) | (PAGE_CACHE_SIZE-1)); | ||
| 669 | } else { | 670 | } else { |
| 670 | pages = alloc_page_vector(num_pages); | 671 | pages = alloc_page_vector(num_pages); |
| 671 | if (IS_ERR(pages)) { | 672 | if (IS_ERR(pages)) { |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 26f883c275e8..261f3e6c0bcf 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
| @@ -997,6 +997,10 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
| 997 | dn, dn->d_name.len, dn->d_name.name); | 997 | dn, dn->d_name.len, dn->d_name.name); |
| 998 | dout("fill_trace doing d_move %p -> %p\n", | 998 | dout("fill_trace doing d_move %p -> %p\n", |
| 999 | req->r_old_dentry, dn); | 999 | req->r_old_dentry, dn); |
| 1000 | |||
| 1001 | /* d_move screws up d_subdirs order */ | ||
| 1002 | ceph_i_clear(dir, CEPH_I_COMPLETE); | ||
| 1003 | |||
| 1000 | d_move(req->r_old_dentry, dn); | 1004 | d_move(req->r_old_dentry, dn); |
| 1001 | dout(" src %p '%.*s' dst %p '%.*s'\n", | 1005 | dout(" src %p '%.*s' dst %p '%.*s'\n", |
| 1002 | req->r_old_dentry, | 1006 | req->r_old_dentry, |
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c index cdaaa131add3..509f57d9ccb3 100644 --- a/fs/ceph/messenger.c +++ b/fs/ceph/messenger.c | |||
| @@ -1334,6 +1334,7 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 1334 | unsigned front_len, middle_len, data_len, data_off; | 1334 | unsigned front_len, middle_len, data_len, data_off; |
| 1335 | int datacrc = con->msgr->nocrc; | 1335 | int datacrc = con->msgr->nocrc; |
| 1336 | int skip; | 1336 | int skip; |
| 1337 | u64 seq; | ||
| 1337 | 1338 | ||
| 1338 | dout("read_partial_message con %p msg %p\n", con, m); | 1339 | dout("read_partial_message con %p msg %p\n", con, m); |
| 1339 | 1340 | ||
| @@ -1368,6 +1369,25 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 1368 | return -EIO; | 1369 | return -EIO; |
| 1369 | data_off = le16_to_cpu(con->in_hdr.data_off); | 1370 | data_off = le16_to_cpu(con->in_hdr.data_off); |
| 1370 | 1371 | ||
| 1372 | /* verify seq# */ | ||
| 1373 | seq = le64_to_cpu(con->in_hdr.seq); | ||
| 1374 | if ((s64)seq - (s64)con->in_seq < 1) { | ||
| 1375 | pr_info("skipping %s%lld %s seq %lld, expected %lld\n", | ||
| 1376 | ENTITY_NAME(con->peer_name), | ||
| 1377 | pr_addr(&con->peer_addr.in_addr), | ||
| 1378 | seq, con->in_seq + 1); | ||
| 1379 | con->in_base_pos = -front_len - middle_len - data_len - | ||
| 1380 | sizeof(m->footer); | ||
| 1381 | con->in_tag = CEPH_MSGR_TAG_READY; | ||
| 1382 | con->in_seq++; | ||
| 1383 | return 0; | ||
| 1384 | } else if ((s64)seq - (s64)con->in_seq > 1) { | ||
| 1385 | pr_err("read_partial_message bad seq %lld expected %lld\n", | ||
| 1386 | seq, con->in_seq + 1); | ||
| 1387 | con->error_msg = "bad message sequence # for incoming message"; | ||
| 1388 | return -EBADMSG; | ||
| 1389 | } | ||
| 1390 | |||
| 1371 | /* allocate message? */ | 1391 | /* allocate message? */ |
| 1372 | if (!con->in_msg) { | 1392 | if (!con->in_msg) { |
| 1373 | dout("got hdr type %d front %d data %d\n", con->in_hdr.type, | 1393 | dout("got hdr type %d front %d data %d\n", con->in_hdr.type, |
| @@ -1379,6 +1399,7 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 1379 | con->in_base_pos = -front_len - middle_len - data_len - | 1399 | con->in_base_pos = -front_len - middle_len - data_len - |
| 1380 | sizeof(m->footer); | 1400 | sizeof(m->footer); |
| 1381 | con->in_tag = CEPH_MSGR_TAG_READY; | 1401 | con->in_tag = CEPH_MSGR_TAG_READY; |
| 1402 | con->in_seq++; | ||
| 1382 | return 0; | 1403 | return 0; |
| 1383 | } | 1404 | } |
| 1384 | if (IS_ERR(con->in_msg)) { | 1405 | if (IS_ERR(con->in_msg)) { |
| @@ -2030,6 +2051,7 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) | |||
| 2030 | ceph_msg_put(con->in_msg); | 2051 | ceph_msg_put(con->in_msg); |
| 2031 | con->in_msg = NULL; | 2052 | con->in_msg = NULL; |
| 2032 | con->in_tag = CEPH_MSGR_TAG_READY; | 2053 | con->in_tag = CEPH_MSGR_TAG_READY; |
| 2054 | con->in_seq++; | ||
| 2033 | } else { | 2055 | } else { |
| 2034 | dout("con_revoke_pages %p msg %p pages %p no-op\n", | 2056 | dout("con_revoke_pages %p msg %p pages %p no-op\n", |
| 2035 | con, con->in_msg, msg); | 2057 | con, con->in_msg, msg); |
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 2b881262ef67..d5114db70453 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
| @@ -869,16 +869,20 @@ skip_inode: | |||
| 869 | continue; | 869 | continue; |
| 870 | ci = ceph_inode(inode); | 870 | ci = ceph_inode(inode); |
| 871 | spin_lock(&inode->i_lock); | 871 | spin_lock(&inode->i_lock); |
| 872 | if (!ci->i_snap_realm) | 872 | if (list_empty(&ci->i_snap_realm_item)) { |
| 873 | goto split_skip_inode; | 873 | struct ceph_snap_realm *oldrealm = |
| 874 | ceph_put_snap_realm(mdsc, ci->i_snap_realm); | 874 | ci->i_snap_realm; |
| 875 | spin_lock(&realm->inodes_with_caps_lock); | 875 | |
| 876 | list_add(&ci->i_snap_realm_item, | 876 | dout(" moving %p to split realm %llx %p\n", |
| 877 | &realm->inodes_with_caps); | 877 | inode, realm->ino, realm); |
| 878 | ci->i_snap_realm = realm; | 878 | spin_lock(&realm->inodes_with_caps_lock); |
| 879 | spin_unlock(&realm->inodes_with_caps_lock); | 879 | list_add(&ci->i_snap_realm_item, |
| 880 | ceph_get_snap_realm(mdsc, realm); | 880 | &realm->inodes_with_caps); |
| 881 | split_skip_inode: | 881 | ci->i_snap_realm = realm; |
| 882 | spin_unlock(&realm->inodes_with_caps_lock); | ||
| 883 | ceph_get_snap_realm(mdsc, realm); | ||
| 884 | ceph_put_snap_realm(mdsc, oldrealm); | ||
| 885 | } | ||
| 882 | spin_unlock(&inode->i_lock); | 886 | spin_unlock(&inode->i_lock); |
| 883 | iput(inode); | 887 | iput(inode); |
| 884 | } | 888 | } |
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 75d02eaa1279..f888cf487b7c 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
| @@ -996,9 +996,10 @@ static int __init init_ceph(void) | |||
| 996 | if (ret) | 996 | if (ret) |
| 997 | goto out_icache; | 997 | goto out_icache; |
| 998 | 998 | ||
| 999 | pr_info("loaded %d.%d.%d (mon/mds/osd proto %d/%d/%d)\n", | 999 | pr_info("loaded (mon/mds/osd proto %d/%d/%d, osdmap %d/%d %d/%d)\n", |
| 1000 | CEPH_VERSION_MAJOR, CEPH_VERSION_MINOR, CEPH_VERSION_PATCH, | 1000 | CEPH_MONC_PROTOCOL, CEPH_MDSC_PROTOCOL, CEPH_OSDC_PROTOCOL, |
| 1001 | CEPH_MONC_PROTOCOL, CEPH_MDSC_PROTOCOL, CEPH_OSDC_PROTOCOL); | 1001 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, |
| 1002 | CEPH_OSDMAP_INC_VERSION, CEPH_OSDMAP_INC_VERSION_EXT); | ||
| 1002 | return 0; | 1003 | return 0; |
| 1003 | 1004 | ||
| 1004 | out_icache: | 1005 | out_icache: |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index e30dfbb056c3..13513b80d87f 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
| 11 | #include <linux/mempool.h> | 11 | #include <linux/mempool.h> |
| 12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
| 13 | #include <linux/slab.h> | ||
| 13 | #include <linux/wait.h> | 14 | #include <linux/wait.h> |
| 14 | #include <linux/writeback.h> | 15 | #include <linux/writeback.h> |
| 15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 4797787c6a44..246a167cb913 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #ifndef _CIFS_FS_SB_H | 18 | #ifndef _CIFS_FS_SB_H |
| 19 | #define _CIFS_FS_SB_H | 19 | #define _CIFS_FS_SB_H |
| 20 | 20 | ||
| 21 | #include <linux/backing-dev.h> | ||
| 22 | |||
| 21 | #define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ | 23 | #define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ |
| 22 | #define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */ | 24 | #define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */ |
| 23 | #define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ | 25 | #define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ |
| @@ -50,5 +52,6 @@ struct cifs_sb_info { | |||
| 50 | #ifdef CONFIG_CIFS_DFS_UPCALL | 52 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 51 | char *mountdata; /* mount options received at mount time */ | 53 | char *mountdata; /* mount options received at mount time */ |
| 52 | #endif | 54 | #endif |
| 55 | struct backing_dev_info bdi; | ||
| 53 | }; | 56 | }; |
| 54 | #endif /* _CIFS_FS_SB_H */ | 57 | #endif /* _CIFS_FS_SB_H */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ded66be6597c..ad235d604a0b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -103,6 +103,12 @@ cifs_read_super(struct super_block *sb, void *data, | |||
| 103 | if (cifs_sb == NULL) | 103 | if (cifs_sb == NULL) |
| 104 | return -ENOMEM; | 104 | return -ENOMEM; |
| 105 | 105 | ||
| 106 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); | ||
| 107 | if (rc) { | ||
| 108 | kfree(cifs_sb); | ||
| 109 | return rc; | ||
| 110 | } | ||
| 111 | |||
| 106 | #ifdef CONFIG_CIFS_DFS_UPCALL | 112 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 107 | /* copy mount params to sb for use in submounts */ | 113 | /* copy mount params to sb for use in submounts */ |
| 108 | /* BB: should we move this after the mount so we | 114 | /* BB: should we move this after the mount so we |
| @@ -115,6 +121,7 @@ cifs_read_super(struct super_block *sb, void *data, | |||
| 115 | int len = strlen(data); | 121 | int len = strlen(data); |
| 116 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); | 122 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); |
| 117 | if (cifs_sb->mountdata == NULL) { | 123 | if (cifs_sb->mountdata == NULL) { |
| 124 | bdi_destroy(&cifs_sb->bdi); | ||
| 118 | kfree(sb->s_fs_info); | 125 | kfree(sb->s_fs_info); |
| 119 | sb->s_fs_info = NULL; | 126 | sb->s_fs_info = NULL; |
| 120 | return -ENOMEM; | 127 | return -ENOMEM; |
| @@ -135,6 +142,7 @@ cifs_read_super(struct super_block *sb, void *data, | |||
| 135 | 142 | ||
| 136 | sb->s_magic = CIFS_MAGIC_NUMBER; | 143 | sb->s_magic = CIFS_MAGIC_NUMBER; |
| 137 | sb->s_op = &cifs_super_ops; | 144 | sb->s_op = &cifs_super_ops; |
| 145 | sb->s_bdi = &cifs_sb->bdi; | ||
| 138 | /* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) | 146 | /* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) |
| 139 | sb->s_blocksize = | 147 | sb->s_blocksize = |
| 140 | cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ | 148 | cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ |
| @@ -183,6 +191,7 @@ out_mount_failed: | |||
| 183 | } | 191 | } |
| 184 | #endif | 192 | #endif |
| 185 | unload_nls(cifs_sb->local_nls); | 193 | unload_nls(cifs_sb->local_nls); |
| 194 | bdi_destroy(&cifs_sb->bdi); | ||
| 186 | kfree(cifs_sb); | 195 | kfree(cifs_sb); |
| 187 | } | 196 | } |
| 188 | return rc; | 197 | return rc; |
| @@ -214,6 +223,7 @@ cifs_put_super(struct super_block *sb) | |||
| 214 | #endif | 223 | #endif |
| 215 | 224 | ||
| 216 | unload_nls(cifs_sb->local_nls); | 225 | unload_nls(cifs_sb->local_nls); |
| 226 | bdi_destroy(&cifs_sb->bdi); | ||
| 217 | kfree(cifs_sb); | 227 | kfree(cifs_sb); |
| 218 | 228 | ||
| 219 | unlock_kernel(); | 229 | unlock_kernel(); |
diff --git a/fs/coda/inode.c b/fs/coda/inode.c index a1695dcadd99..d97f9935a028 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c | |||
| @@ -167,6 +167,10 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) | |||
| 167 | return -EBUSY; | 167 | return -EBUSY; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY); | ||
| 171 | if (error) | ||
| 172 | goto bdi_err; | ||
| 173 | |||
| 170 | vc->vc_sb = sb; | 174 | vc->vc_sb = sb; |
| 171 | 175 | ||
| 172 | sb->s_fs_info = vc; | 176 | sb->s_fs_info = vc; |
| @@ -175,6 +179,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) | |||
| 175 | sb->s_blocksize_bits = 12; | 179 | sb->s_blocksize_bits = 12; |
| 176 | sb->s_magic = CODA_SUPER_MAGIC; | 180 | sb->s_magic = CODA_SUPER_MAGIC; |
| 177 | sb->s_op = &coda_super_operations; | 181 | sb->s_op = &coda_super_operations; |
| 182 | sb->s_bdi = &vc->bdi; | ||
| 178 | 183 | ||
| 179 | /* get root fid from Venus: this needs the root inode */ | 184 | /* get root fid from Venus: this needs the root inode */ |
| 180 | error = venus_rootfid(sb, &fid); | 185 | error = venus_rootfid(sb, &fid); |
| @@ -200,6 +205,8 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) | |||
| 200 | return 0; | 205 | return 0; |
| 201 | 206 | ||
| 202 | error: | 207 | error: |
| 208 | bdi_destroy(&vc->bdi); | ||
| 209 | bdi_err: | ||
| 203 | if (root) | 210 | if (root) |
| 204 | iput(root); | 211 | iput(root); |
| 205 | if (vc) | 212 | if (vc) |
| @@ -210,6 +217,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) | |||
| 210 | 217 | ||
| 211 | static void coda_put_super(struct super_block *sb) | 218 | static void coda_put_super(struct super_block *sb) |
| 212 | { | 219 | { |
| 220 | bdi_destroy(&coda_vcp(sb)->bdi); | ||
| 213 | coda_vcp(sb)->vc_sb = NULL; | 221 | coda_vcp(sb)->vc_sb = NULL; |
| 214 | sb->s_fs_info = NULL; | 222 | sb->s_fs_info = NULL; |
| 215 | 223 | ||
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c32a1b6a856b..641640dc7ae5 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -102,7 +102,6 @@ | |||
| 102 | #include <linux/nbd.h> | 102 | #include <linux/nbd.h> |
| 103 | #include <linux/random.h> | 103 | #include <linux/random.h> |
| 104 | #include <linux/filter.h> | 104 | #include <linux/filter.h> |
| 105 | #include <linux/pktcdvd.h> | ||
| 106 | 105 | ||
| 107 | #include <linux/hiddev.h> | 106 | #include <linux/hiddev.h> |
| 108 | 107 | ||
| @@ -1126,8 +1125,6 @@ COMPATIBLE_IOCTL(PPGETMODE) | |||
| 1126 | COMPATIBLE_IOCTL(PPGETPHASE) | 1125 | COMPATIBLE_IOCTL(PPGETPHASE) |
| 1127 | COMPATIBLE_IOCTL(PPGETFLAGS) | 1126 | COMPATIBLE_IOCTL(PPGETFLAGS) |
| 1128 | COMPATIBLE_IOCTL(PPSETFLAGS) | 1127 | COMPATIBLE_IOCTL(PPSETFLAGS) |
| 1129 | /* pktcdvd */ | ||
| 1130 | COMPATIBLE_IOCTL(PACKET_CTRL_CMD) | ||
| 1131 | /* Big A */ | 1128 | /* Big A */ |
| 1132 | /* sparc only */ | 1129 | /* sparc only */ |
| 1133 | /* Big Q for sound/OSS */ | 1130 | /* Big Q for sound/OSS */ |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index bc7115403f38..bfc2e0f78f00 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/scatterlist.h> | 35 | #include <linux/scatterlist.h> |
| 36 | #include <linux/hash.h> | 36 | #include <linux/hash.h> |
| 37 | #include <linux/nsproxy.h> | 37 | #include <linux/nsproxy.h> |
| 38 | #include <linux/backing-dev.h> | ||
| 38 | 39 | ||
| 39 | /* Version verification for shared data structures w/ userspace */ | 40 | /* Version verification for shared data structures w/ userspace */ |
| 40 | #define ECRYPTFS_VERSION_MAJOR 0x00 | 41 | #define ECRYPTFS_VERSION_MAJOR 0x00 |
| @@ -393,6 +394,7 @@ struct ecryptfs_mount_crypt_stat { | |||
| 393 | struct ecryptfs_sb_info { | 394 | struct ecryptfs_sb_info { |
| 394 | struct super_block *wsi_sb; | 395 | struct super_block *wsi_sb; |
| 395 | struct ecryptfs_mount_crypt_stat mount_crypt_stat; | 396 | struct ecryptfs_mount_crypt_stat mount_crypt_stat; |
| 397 | struct backing_dev_info bdi; | ||
| 396 | }; | 398 | }; |
| 397 | 399 | ||
| 398 | /* file private data. */ | 400 | /* file private data. */ |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index af1a8f01ebac..760983d0f25e 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
| @@ -497,17 +497,25 @@ struct kmem_cache *ecryptfs_sb_info_cache; | |||
| 497 | static int | 497 | static int |
| 498 | ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent) | 498 | ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent) |
| 499 | { | 499 | { |
| 500 | struct ecryptfs_sb_info *esi; | ||
| 500 | int rc = 0; | 501 | int rc = 0; |
| 501 | 502 | ||
| 502 | /* Released in ecryptfs_put_super() */ | 503 | /* Released in ecryptfs_put_super() */ |
| 503 | ecryptfs_set_superblock_private(sb, | 504 | ecryptfs_set_superblock_private(sb, |
| 504 | kmem_cache_zalloc(ecryptfs_sb_info_cache, | 505 | kmem_cache_zalloc(ecryptfs_sb_info_cache, |
| 505 | GFP_KERNEL)); | 506 | GFP_KERNEL)); |
| 506 | if (!ecryptfs_superblock_to_private(sb)) { | 507 | esi = ecryptfs_superblock_to_private(sb); |
| 508 | if (!esi) { | ||
| 507 | ecryptfs_printk(KERN_WARNING, "Out of memory\n"); | 509 | ecryptfs_printk(KERN_WARNING, "Out of memory\n"); |
| 508 | rc = -ENOMEM; | 510 | rc = -ENOMEM; |
| 509 | goto out; | 511 | goto out; |
| 510 | } | 512 | } |
| 513 | |||
| 514 | rc = bdi_setup_and_register(&esi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); | ||
| 515 | if (rc) | ||
| 516 | goto out; | ||
| 517 | |||
| 518 | sb->s_bdi = &esi->bdi; | ||
| 511 | sb->s_op = &ecryptfs_sops; | 519 | sb->s_op = &ecryptfs_sops; |
| 512 | /* Released through deactivate_super(sb) from get_sb_nodev */ | 520 | /* Released through deactivate_super(sb) from get_sb_nodev */ |
| 513 | sb->s_root = d_alloc(NULL, &(const struct qstr) { | 521 | sb->s_root = d_alloc(NULL, &(const struct qstr) { |
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 278743c7716a..0c0ae491d231 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
| @@ -122,6 +122,7 @@ static void ecryptfs_put_super(struct super_block *sb) | |||
| 122 | lock_kernel(); | 122 | lock_kernel(); |
| 123 | 123 | ||
| 124 | ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat); | 124 | ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat); |
| 125 | bdi_destroy(&sb_info->bdi); | ||
| 125 | kmem_cache_free(ecryptfs_sb_info_cache, sb_info); | 126 | kmem_cache_free(ecryptfs_sb_info_cache, sb_info); |
| 126 | ecryptfs_set_superblock_private(sb, NULL); | 127 | ecryptfs_set_superblock_private(sb, NULL); |
| 127 | 128 | ||
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 8442e353309f..22721b2fd890 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
| 37 | #include <linux/time.h> | 37 | #include <linux/time.h> |
| 38 | #include <linux/backing-dev.h> | ||
| 38 | #include "common.h" | 39 | #include "common.h" |
| 39 | 40 | ||
| 40 | /* FIXME: Remove once pnfs hits mainline | 41 | /* FIXME: Remove once pnfs hits mainline |
| @@ -84,6 +85,7 @@ struct exofs_sb_info { | |||
| 84 | u32 s_next_generation; /* next gen # to use */ | 85 | u32 s_next_generation; /* next gen # to use */ |
| 85 | atomic_t s_curr_pending; /* number of pending commands */ | 86 | atomic_t s_curr_pending; /* number of pending commands */ |
| 86 | uint8_t s_cred[OSD_CAP_LEN]; /* credential for the fscb */ | 87 | uint8_t s_cred[OSD_CAP_LEN]; /* credential for the fscb */ |
| 88 | struct backing_dev_info bdi; /* register our bdi with VFS */ | ||
| 87 | 89 | ||
| 88 | struct pnfs_osd_data_map data_map; /* Default raid to use | 90 | struct pnfs_osd_data_map data_map; /* Default raid to use |
| 89 | * FIXME: Needed ? | 91 | * FIXME: Needed ? |
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 18e57ea1e5b4..03149b9a5178 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
| @@ -302,6 +302,7 @@ static void exofs_put_super(struct super_block *sb) | |||
| 302 | _exofs_print_device("Unmounting", NULL, sbi->layout.s_ods[0], | 302 | _exofs_print_device("Unmounting", NULL, sbi->layout.s_ods[0], |
| 303 | sbi->layout.s_pid); | 303 | sbi->layout.s_pid); |
| 304 | 304 | ||
| 305 | bdi_destroy(&sbi->bdi); | ||
| 305 | exofs_free_sbi(sbi); | 306 | exofs_free_sbi(sbi); |
| 306 | sb->s_fs_info = NULL; | 307 | sb->s_fs_info = NULL; |
| 307 | } | 308 | } |
| @@ -546,6 +547,10 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 546 | if (!sbi) | 547 | if (!sbi) |
| 547 | return -ENOMEM; | 548 | return -ENOMEM; |
| 548 | 549 | ||
| 550 | ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY); | ||
| 551 | if (ret) | ||
| 552 | goto free_bdi; | ||
| 553 | |||
| 549 | /* use mount options to fill superblock */ | 554 | /* use mount options to fill superblock */ |
| 550 | od = osduld_path_lookup(opts->dev_name); | 555 | od = osduld_path_lookup(opts->dev_name); |
| 551 | if (IS_ERR(od)) { | 556 | if (IS_ERR(od)) { |
| @@ -612,6 +617,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 612 | } | 617 | } |
| 613 | 618 | ||
| 614 | /* set up operation vectors */ | 619 | /* set up operation vectors */ |
| 620 | sb->s_bdi = &sbi->bdi; | ||
| 615 | sb->s_fs_info = sbi; | 621 | sb->s_fs_info = sbi; |
| 616 | sb->s_op = &exofs_sops; | 622 | sb->s_op = &exofs_sops; |
| 617 | sb->s_export_op = &exofs_export_ops; | 623 | sb->s_export_op = &exofs_export_ops; |
| @@ -643,6 +649,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 643 | return 0; | 649 | return 0; |
| 644 | 650 | ||
| 645 | free_sbi: | 651 | free_sbi: |
| 652 | bdi_destroy(&sbi->bdi); | ||
| 653 | free_bdi: | ||
| 646 | EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", | 654 | EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", |
| 647 | opts->dev_name, sbi->layout.s_pid, ret); | 655 | opts->dev_name, sbi->layout.s_pid, ret); |
| 648 | exofs_free_sbi(sbi); | 656 | exofs_free_sbi(sbi); |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 94c8ee81f5e1..236b834b4ca8 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -3879,6 +3879,7 @@ static int ext4_xattr_fiemap(struct inode *inode, | |||
| 3879 | physical += offset; | 3879 | physical += offset; |
| 3880 | length = EXT4_SB(inode->i_sb)->s_inode_size - offset; | 3880 | length = EXT4_SB(inode->i_sb)->s_inode_size - offset; |
| 3881 | flags |= FIEMAP_EXTENT_DATA_INLINE; | 3881 | flags |= FIEMAP_EXTENT_DATA_INLINE; |
| 3882 | brelse(iloc.bh); | ||
| 3882 | } else { /* external block */ | 3883 | } else { /* external block */ |
| 3883 | physical = EXT4_I(inode)->i_file_acl << blockbits; | 3884 | physical = EXT4_I(inode)->i_file_acl << blockbits; |
| 3884 | length = inode->i_sb->s_blocksize; | 3885 | length = inode->i_sb->s_blocksize; |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 5381802d6052..81d605412844 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -5375,7 +5375,7 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 5375 | } else { | 5375 | } else { |
| 5376 | struct ext4_iloc iloc; | 5376 | struct ext4_iloc iloc; |
| 5377 | 5377 | ||
| 5378 | err = ext4_get_inode_loc(inode, &iloc); | 5378 | err = __ext4_get_inode_loc(inode, &iloc, 0); |
| 5379 | if (err) | 5379 | if (err) |
| 5380 | return err; | 5380 | return err; |
| 5381 | if (wbc->sync_mode == WB_SYNC_ALL) | 5381 | if (wbc->sync_mode == WB_SYNC_ALL) |
| @@ -5386,6 +5386,7 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 5386 | (unsigned long long)iloc.bh->b_blocknr); | 5386 | (unsigned long long)iloc.bh->b_blocknr); |
| 5387 | err = -EIO; | 5387 | err = -EIO; |
| 5388 | } | 5388 | } |
| 5389 | brelse(iloc.bh); | ||
| 5389 | } | 5390 | } |
| 5390 | return err; | 5391 | return err; |
| 5391 | } | 5392 | } |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index bde9d0b170c2..b423a364dca3 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -2535,6 +2535,17 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
| 2535 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", | 2535 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", |
| 2536 | entry->count, entry->group, entry); | 2536 | entry->count, entry->group, entry); |
| 2537 | 2537 | ||
| 2538 | if (test_opt(sb, DISCARD)) { | ||
| 2539 | ext4_fsblk_t discard_block; | ||
| 2540 | |||
| 2541 | discard_block = entry->start_blk + | ||
| 2542 | ext4_group_first_block_no(sb, entry->group); | ||
| 2543 | trace_ext4_discard_blocks(sb, | ||
| 2544 | (unsigned long long)discard_block, | ||
| 2545 | entry->count); | ||
| 2546 | sb_issue_discard(sb, discard_block, entry->count); | ||
| 2547 | } | ||
| 2548 | |||
| 2538 | err = ext4_mb_load_buddy(sb, entry->group, &e4b); | 2549 | err = ext4_mb_load_buddy(sb, entry->group, &e4b); |
| 2539 | /* we expect to find existing buddy because it's pinned */ | 2550 | /* we expect to find existing buddy because it's pinned */ |
| 2540 | BUG_ON(err != 0); | 2551 | BUG_ON(err != 0); |
| @@ -2556,16 +2567,6 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
| 2556 | page_cache_release(e4b.bd_bitmap_page); | 2567 | page_cache_release(e4b.bd_bitmap_page); |
| 2557 | } | 2568 | } |
| 2558 | ext4_unlock_group(sb, entry->group); | 2569 | ext4_unlock_group(sb, entry->group); |
| 2559 | if (test_opt(sb, DISCARD)) { | ||
| 2560 | ext4_fsblk_t discard_block; | ||
| 2561 | |||
| 2562 | discard_block = entry->start_blk + | ||
| 2563 | ext4_group_first_block_no(sb, entry->group); | ||
| 2564 | trace_ext4_discard_blocks(sb, | ||
| 2565 | (unsigned long long)discard_block, | ||
| 2566 | entry->count); | ||
| 2567 | sb_issue_discard(sb, discard_block, entry->count); | ||
| 2568 | } | ||
| 2569 | kmem_cache_free(ext4_free_ext_cachep, entry); | 2570 | kmem_cache_free(ext4_free_ext_cachep, entry); |
| 2570 | ext4_mb_release_desc(&e4b); | 2571 | ext4_mb_release_desc(&e4b); |
| 2571 | } | 2572 | } |
diff --git a/fs/ioctl.c b/fs/ioctl.c index 6c751106c2e5..7faefb4da939 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
| @@ -228,14 +228,23 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg) | |||
| 228 | 228 | ||
| 229 | #ifdef CONFIG_BLOCK | 229 | #ifdef CONFIG_BLOCK |
| 230 | 230 | ||
| 231 | #define blk_to_logical(inode, blk) (blk << (inode)->i_blkbits) | 231 | static inline sector_t logical_to_blk(struct inode *inode, loff_t offset) |
| 232 | #define logical_to_blk(inode, offset) (offset >> (inode)->i_blkbits); | 232 | { |
| 233 | return (offset >> inode->i_blkbits); | ||
| 234 | } | ||
| 235 | |||
| 236 | static inline loff_t blk_to_logical(struct inode *inode, sector_t blk) | ||
| 237 | { | ||
| 238 | return (blk << inode->i_blkbits); | ||
| 239 | } | ||
| 233 | 240 | ||
| 234 | /** | 241 | /** |
| 235 | * __generic_block_fiemap - FIEMAP for block based inodes (no locking) | 242 | * __generic_block_fiemap - FIEMAP for block based inodes (no locking) |
| 236 | * @inode - the inode to map | 243 | * @inode: the inode to map |
| 237 | * @arg - the pointer to userspace where we copy everything to | 244 | * @fieinfo: the fiemap info struct that will be passed back to userspace |
| 238 | * @get_block - the fs's get_block function | 245 | * @start: where to start mapping in the inode |
| 246 | * @len: how much space to map | ||
| 247 | * @get_block: the fs's get_block function | ||
| 239 | * | 248 | * |
| 240 | * This does FIEMAP for block based inodes. Basically it will just loop | 249 | * This does FIEMAP for block based inodes. Basically it will just loop |
| 241 | * through get_block until we hit the number of extents we want to map, or we | 250 | * through get_block until we hit the number of extents we want to map, or we |
| @@ -250,58 +259,63 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg) | |||
| 250 | */ | 259 | */ |
| 251 | 260 | ||
| 252 | int __generic_block_fiemap(struct inode *inode, | 261 | int __generic_block_fiemap(struct inode *inode, |
| 253 | struct fiemap_extent_info *fieinfo, u64 start, | 262 | struct fiemap_extent_info *fieinfo, loff_t start, |
| 254 | u64 len, get_block_t *get_block) | 263 | loff_t len, get_block_t *get_block) |
| 255 | { | 264 | { |
| 256 | struct buffer_head tmp; | 265 | struct buffer_head map_bh; |
| 257 | unsigned long long start_blk; | 266 | sector_t start_blk, last_blk; |
| 258 | long long length = 0, map_len = 0; | 267 | loff_t isize = i_size_read(inode); |
| 259 | u64 logical = 0, phys = 0, size = 0; | 268 | u64 logical = 0, phys = 0, size = 0; |
| 260 | u32 flags = FIEMAP_EXTENT_MERGED; | 269 | u32 flags = FIEMAP_EXTENT_MERGED; |
| 261 | int ret = 0, past_eof = 0, whole_file = 0; | 270 | bool past_eof = false, whole_file = false; |
| 271 | int ret = 0; | ||
| 262 | 272 | ||
| 263 | if ((ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC))) | 273 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); |
| 274 | if (ret) | ||
| 264 | return ret; | 275 | return ret; |
| 265 | 276 | ||
| 266 | start_blk = logical_to_blk(inode, start); | 277 | /* |
| 267 | 278 | * Either the i_mutex or other appropriate locking needs to be held | |
| 268 | length = (long long)min_t(u64, len, i_size_read(inode)); | 279 | * since we expect isize to not change at all through the duration of |
| 269 | if (length < len) | 280 | * this call. |
| 270 | whole_file = 1; | 281 | */ |
| 282 | if (len >= isize) { | ||
| 283 | whole_file = true; | ||
| 284 | len = isize; | ||
| 285 | } | ||
| 271 | 286 | ||
| 272 | map_len = length; | 287 | start_blk = logical_to_blk(inode, start); |
| 288 | last_blk = logical_to_blk(inode, start + len - 1); | ||
| 273 | 289 | ||
| 274 | do { | 290 | do { |
| 275 | /* | 291 | /* |
| 276 | * we set b_size to the total size we want so it will map as | 292 | * we set b_size to the total size we want so it will map as |
| 277 | * many contiguous blocks as possible at once | 293 | * many contiguous blocks as possible at once |
| 278 | */ | 294 | */ |
| 279 | memset(&tmp, 0, sizeof(struct buffer_head)); | 295 | memset(&map_bh, 0, sizeof(struct buffer_head)); |
| 280 | tmp.b_size = map_len; | 296 | map_bh.b_size = len; |
| 281 | 297 | ||
| 282 | ret = get_block(inode, start_blk, &tmp, 0); | 298 | ret = get_block(inode, start_blk, &map_bh, 0); |
| 283 | if (ret) | 299 | if (ret) |
| 284 | break; | 300 | break; |
| 285 | 301 | ||
| 286 | /* HOLE */ | 302 | /* HOLE */ |
| 287 | if (!buffer_mapped(&tmp)) { | 303 | if (!buffer_mapped(&map_bh)) { |
| 288 | length -= blk_to_logical(inode, 1); | ||
| 289 | start_blk++; | 304 | start_blk++; |
| 290 | 305 | ||
| 291 | /* | 306 | /* |
| 292 | * we want to handle the case where there is an | 307 | * We want to handle the case where there is an |
| 293 | * allocated block at the front of the file, and then | 308 | * allocated block at the front of the file, and then |
| 294 | * nothing but holes up to the end of the file properly, | 309 | * nothing but holes up to the end of the file properly, |
| 295 | * to make sure that extent at the front gets properly | 310 | * to make sure that extent at the front gets properly |
| 296 | * marked with FIEMAP_EXTENT_LAST | 311 | * marked with FIEMAP_EXTENT_LAST |
| 297 | */ | 312 | */ |
| 298 | if (!past_eof && | 313 | if (!past_eof && |
| 299 | blk_to_logical(inode, start_blk) >= | 314 | blk_to_logical(inode, start_blk) >= isize) |
| 300 | blk_to_logical(inode, 0)+i_size_read(inode)) | ||
| 301 | past_eof = 1; | 315 | past_eof = 1; |
| 302 | 316 | ||
| 303 | /* | 317 | /* |
| 304 | * first hole after going past the EOF, this is our | 318 | * First hole after going past the EOF, this is our |
| 305 | * last extent | 319 | * last extent |
| 306 | */ | 320 | */ |
| 307 | if (past_eof && size) { | 321 | if (past_eof && size) { |
| @@ -309,15 +323,18 @@ int __generic_block_fiemap(struct inode *inode, | |||
| 309 | ret = fiemap_fill_next_extent(fieinfo, logical, | 323 | ret = fiemap_fill_next_extent(fieinfo, logical, |
| 310 | phys, size, | 324 | phys, size, |
| 311 | flags); | 325 | flags); |
| 312 | break; | 326 | } else if (size) { |
| 327 | ret = fiemap_fill_next_extent(fieinfo, logical, | ||
| 328 | phys, size, flags); | ||
| 329 | size = 0; | ||
| 313 | } | 330 | } |
| 314 | 331 | ||
| 315 | /* if we have holes up to/past EOF then we're done */ | 332 | /* if we have holes up to/past EOF then we're done */ |
| 316 | if (length <= 0 || past_eof) | 333 | if (start_blk > last_blk || past_eof || ret) |
| 317 | break; | 334 | break; |
| 318 | } else { | 335 | } else { |
| 319 | /* | 336 | /* |
| 320 | * we have gone over the length of what we wanted to | 337 | * We have gone over the length of what we wanted to |
| 321 | * map, and it wasn't the entire file, so add the extent | 338 | * map, and it wasn't the entire file, so add the extent |
| 322 | * we got last time and exit. | 339 | * we got last time and exit. |
| 323 | * | 340 | * |
| @@ -331,7 +348,7 @@ int __generic_block_fiemap(struct inode *inode, | |||
| 331 | * are good to go, just add the extent to the fieinfo | 348 | * are good to go, just add the extent to the fieinfo |
| 332 | * and break | 349 | * and break |
| 333 | */ | 350 | */ |
| 334 | if (length <= 0 && !whole_file) { | 351 | if (start_blk > last_blk && !whole_file) { |
| 335 | ret = fiemap_fill_next_extent(fieinfo, logical, | 352 | ret = fiemap_fill_next_extent(fieinfo, logical, |
| 336 | phys, size, | 353 | phys, size, |
| 337 | flags); | 354 | flags); |
| @@ -351,11 +368,10 @@ int __generic_block_fiemap(struct inode *inode, | |||
| 351 | } | 368 | } |
| 352 | 369 | ||
| 353 | logical = blk_to_logical(inode, start_blk); | 370 | logical = blk_to_logical(inode, start_blk); |
| 354 | phys = blk_to_logical(inode, tmp.b_blocknr); | 371 | phys = blk_to_logical(inode, map_bh.b_blocknr); |
| 355 | size = tmp.b_size; | 372 | size = map_bh.b_size; |
| 356 | flags = FIEMAP_EXTENT_MERGED; | 373 | flags = FIEMAP_EXTENT_MERGED; |
| 357 | 374 | ||
| 358 | length -= tmp.b_size; | ||
| 359 | start_blk += logical_to_blk(inode, size); | 375 | start_blk += logical_to_blk(inode, size); |
| 360 | 376 | ||
| 361 | /* | 377 | /* |
| @@ -363,15 +379,13 @@ int __generic_block_fiemap(struct inode *inode, | |||
| 363 | * soon as we find a hole that the last extent we found | 379 | * soon as we find a hole that the last extent we found |
| 364 | * is marked with FIEMAP_EXTENT_LAST | 380 | * is marked with FIEMAP_EXTENT_LAST |
| 365 | */ | 381 | */ |
| 366 | if (!past_eof && | 382 | if (!past_eof && logical + size >= isize) |
| 367 | logical+size >= | 383 | past_eof = true; |
| 368 | blk_to_logical(inode, 0)+i_size_read(inode)) | ||
| 369 | past_eof = 1; | ||
| 370 | } | 384 | } |
| 371 | cond_resched(); | 385 | cond_resched(); |
| 372 | } while (1); | 386 | } while (1); |
| 373 | 387 | ||
| 374 | /* if ret is 1 then we just hit the end of the extent array */ | 388 | /* If ret is 1 then we just hit the end of the extent array */ |
| 375 | if (ret == 1) | 389 | if (ret == 1) |
| 376 | ret = 0; | 390 | ret = 0; |
| 377 | 391 | ||
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index cf98da1be23e..fa3385154023 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
| @@ -526,10 +526,15 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
| 526 | sb->s_blocksize_bits = 10; | 526 | sb->s_blocksize_bits = 10; |
| 527 | sb->s_magic = NCP_SUPER_MAGIC; | 527 | sb->s_magic = NCP_SUPER_MAGIC; |
| 528 | sb->s_op = &ncp_sops; | 528 | sb->s_op = &ncp_sops; |
| 529 | sb->s_bdi = &server->bdi; | ||
| 529 | 530 | ||
| 530 | server = NCP_SBP(sb); | 531 | server = NCP_SBP(sb); |
| 531 | memset(server, 0, sizeof(*server)); | 532 | memset(server, 0, sizeof(*server)); |
| 532 | 533 | ||
| 534 | error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY); | ||
| 535 | if (error) | ||
| 536 | goto out_bdi; | ||
| 537 | |||
| 533 | server->ncp_filp = ncp_filp; | 538 | server->ncp_filp = ncp_filp; |
| 534 | server->ncp_sock = sock; | 539 | server->ncp_sock = sock; |
| 535 | 540 | ||
| @@ -719,6 +724,8 @@ out_fput2: | |||
| 719 | if (server->info_filp) | 724 | if (server->info_filp) |
| 720 | fput(server->info_filp); | 725 | fput(server->info_filp); |
| 721 | out_fput: | 726 | out_fput: |
| 727 | bdi_destroy(&server->bdi); | ||
| 728 | out_bdi: | ||
| 722 | /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: | 729 | /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: |
| 723 | * | 730 | * |
| 724 | * The previously used put_filp(ncp_filp); was bogous, since | 731 | * The previously used put_filp(ncp_filp); was bogous, since |
| @@ -756,6 +763,7 @@ static void ncp_put_super(struct super_block *sb) | |||
| 756 | kill_pid(server->m.wdog_pid, SIGTERM, 1); | 763 | kill_pid(server->m.wdog_pid, SIGTERM, 1); |
| 757 | put_pid(server->m.wdog_pid); | 764 | put_pid(server->m.wdog_pid); |
| 758 | 765 | ||
| 766 | bdi_destroy(&server->bdi); | ||
| 759 | kfree(server->priv.data); | 767 | kfree(server->priv.data); |
| 760 | kfree(server->auth.object_name); | 768 | kfree(server->auth.object_name); |
| 761 | vfree(server->rxbuf); | 769 | vfree(server->rxbuf); |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a8766c4ef2e0..acc9c4943b84 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -966,6 +966,8 @@ out_error: | |||
| 966 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) | 966 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) |
| 967 | { | 967 | { |
| 968 | target->flags = source->flags; | 968 | target->flags = source->flags; |
| 969 | target->rsize = source->rsize; | ||
| 970 | target->wsize = source->wsize; | ||
| 969 | target->acregmin = source->acregmin; | 971 | target->acregmin = source->acregmin; |
| 970 | target->acregmax = source->acregmax; | 972 | target->acregmax = source->acregmax; |
| 971 | target->acdirmin = source->acdirmin; | 973 | target->acdirmin = source->acdirmin; |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index be46f26c9a56..a7bb5c694aa3 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -837,6 +837,8 @@ out_zap_parent: | |||
| 837 | /* If we have submounts, don't unhash ! */ | 837 | /* If we have submounts, don't unhash ! */ |
| 838 | if (have_submounts(dentry)) | 838 | if (have_submounts(dentry)) |
| 839 | goto out_valid; | 839 | goto out_valid; |
| 840 | if (dentry->d_flags & DCACHE_DISCONNECTED) | ||
| 841 | goto out_valid; | ||
| 840 | shrink_dcache_parent(dentry); | 842 | shrink_dcache_parent(dentry); |
| 841 | } | 843 | } |
| 842 | d_drop(dentry); | 844 | d_drop(dentry); |
| @@ -1050,7 +1052,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1050 | struct inode *dir; | 1052 | struct inode *dir; |
| 1051 | int openflags, ret = 0; | 1053 | int openflags, ret = 0; |
| 1052 | 1054 | ||
| 1053 | if (!is_atomic_open(nd)) | 1055 | if (!is_atomic_open(nd) || d_mountpoint(dentry)) |
| 1054 | goto no_open; | 1056 | goto no_open; |
| 1055 | parent = dget_parent(dentry); | 1057 | parent = dget_parent(dentry); |
| 1056 | dir = parent->d_inode; | 1058 | dir = parent->d_inode; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 638067007c65..071fcedd517c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -5218,9 +5218,12 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
| 5218 | msg.rpc_resp = &calldata->res; | 5218 | msg.rpc_resp = &calldata->res; |
| 5219 | task_setup_data.callback_data = calldata; | 5219 | task_setup_data.callback_data = calldata; |
| 5220 | task = rpc_run_task(&task_setup_data); | 5220 | task = rpc_run_task(&task_setup_data); |
| 5221 | if (IS_ERR(task)) | 5221 | if (IS_ERR(task)) { |
| 5222 | status = PTR_ERR(task); | 5222 | status = PTR_ERR(task); |
| 5223 | goto out; | ||
| 5224 | } | ||
| 5223 | rpc_put_task(task); | 5225 | rpc_put_task(task); |
| 5226 | return 0; | ||
| 5224 | out: | 5227 | out: |
| 5225 | dprintk("<-- %s status=%d\n", __func__, status); | 5228 | dprintk("<-- %s status=%d\n", __func__, status); |
| 5226 | return status; | 5229 | return status; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index e01637240eeb..b4148fc00f9f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -2187,6 +2187,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
| 2187 | if (data->version == 4) { | 2187 | if (data->version == 4) { |
| 2188 | error = nfs4_try_mount(flags, dev_name, data, mnt); | 2188 | error = nfs4_try_mount(flags, dev_name, data, mnt); |
| 2189 | kfree(data->client_address); | 2189 | kfree(data->client_address); |
| 2190 | kfree(data->nfs_server.export_path); | ||
| 2190 | goto out; | 2191 | goto out; |
| 2191 | } | 2192 | } |
| 2192 | #endif /* CONFIG_NFS_V4 */ | 2193 | #endif /* CONFIG_NFS_V4 */ |
| @@ -2657,7 +2658,7 @@ static void nfs_fix_devname(const struct path *path, struct vfsmount *mnt) | |||
| 2657 | devname = nfs_path(path->mnt->mnt_devname, | 2658 | devname = nfs_path(path->mnt->mnt_devname, |
| 2658 | path->mnt->mnt_root, path->dentry, | 2659 | path->mnt->mnt_root, path->dentry, |
| 2659 | page, PAGE_SIZE); | 2660 | page, PAGE_SIZE); |
| 2660 | if (devname == NULL) | 2661 | if (IS_ERR(devname)) |
| 2661 | goto out_freepage; | 2662 | goto out_freepage; |
| 2662 | tmp = kstrdup(devname, GFP_KERNEL); | 2663 | tmp = kstrdup(devname, GFP_KERNEL); |
| 2663 | if (tmp == NULL) | 2664 | if (tmp == NULL) |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index de38d63aa920..3aea3ca98ab7 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -1201,6 +1201,25 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
| 1201 | 1201 | ||
| 1202 | 1202 | ||
| 1203 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1203 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
| 1204 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) | ||
| 1205 | { | ||
| 1206 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) | ||
| 1207 | return 1; | ||
| 1208 | if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, | ||
| 1209 | NFS_INO_COMMIT, nfs_wait_bit_killable, | ||
| 1210 | TASK_KILLABLE)) | ||
| 1211 | return 1; | ||
| 1212 | return 0; | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | static void nfs_commit_clear_lock(struct nfs_inode *nfsi) | ||
| 1216 | { | ||
| 1217 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); | ||
| 1218 | smp_mb__after_clear_bit(); | ||
| 1219 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | |||
| 1204 | static void nfs_commitdata_release(void *data) | 1223 | static void nfs_commitdata_release(void *data) |
| 1205 | { | 1224 | { |
| 1206 | struct nfs_write_data *wdata = data; | 1225 | struct nfs_write_data *wdata = data; |
| @@ -1262,8 +1281,6 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
| 1262 | task = rpc_run_task(&task_setup_data); | 1281 | task = rpc_run_task(&task_setup_data); |
| 1263 | if (IS_ERR(task)) | 1282 | if (IS_ERR(task)) |
| 1264 | return PTR_ERR(task); | 1283 | return PTR_ERR(task); |
| 1265 | if (how & FLUSH_SYNC) | ||
| 1266 | rpc_wait_for_completion_task(task); | ||
| 1267 | rpc_put_task(task); | 1284 | rpc_put_task(task); |
| 1268 | return 0; | 1285 | return 0; |
| 1269 | } | 1286 | } |
| @@ -1294,6 +1311,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
| 1294 | BDI_RECLAIMABLE); | 1311 | BDI_RECLAIMABLE); |
| 1295 | nfs_clear_page_tag_locked(req); | 1312 | nfs_clear_page_tag_locked(req); |
| 1296 | } | 1313 | } |
| 1314 | nfs_commit_clear_lock(NFS_I(inode)); | ||
| 1297 | return -ENOMEM; | 1315 | return -ENOMEM; |
| 1298 | } | 1316 | } |
| 1299 | 1317 | ||
| @@ -1349,6 +1367,7 @@ static void nfs_commit_release(void *calldata) | |||
| 1349 | next: | 1367 | next: |
| 1350 | nfs_clear_page_tag_locked(req); | 1368 | nfs_clear_page_tag_locked(req); |
| 1351 | } | 1369 | } |
| 1370 | nfs_commit_clear_lock(NFS_I(data->inode)); | ||
| 1352 | nfs_commitdata_release(calldata); | 1371 | nfs_commitdata_release(calldata); |
| 1353 | } | 1372 | } |
| 1354 | 1373 | ||
| @@ -1363,8 +1382,11 @@ static const struct rpc_call_ops nfs_commit_ops = { | |||
| 1363 | static int nfs_commit_inode(struct inode *inode, int how) | 1382 | static int nfs_commit_inode(struct inode *inode, int how) |
| 1364 | { | 1383 | { |
| 1365 | LIST_HEAD(head); | 1384 | LIST_HEAD(head); |
| 1366 | int res; | 1385 | int may_wait = how & FLUSH_SYNC; |
| 1386 | int res = 0; | ||
| 1367 | 1387 | ||
| 1388 | if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) | ||
| 1389 | goto out; | ||
| 1368 | spin_lock(&inode->i_lock); | 1390 | spin_lock(&inode->i_lock); |
| 1369 | res = nfs_scan_commit(inode, &head, 0, 0); | 1391 | res = nfs_scan_commit(inode, &head, 0, 0); |
| 1370 | spin_unlock(&inode->i_lock); | 1392 | spin_unlock(&inode->i_lock); |
| @@ -1372,7 +1394,13 @@ static int nfs_commit_inode(struct inode *inode, int how) | |||
| 1372 | int error = nfs_commit_list(inode, &head, how); | 1394 | int error = nfs_commit_list(inode, &head, how); |
| 1373 | if (error < 0) | 1395 | if (error < 0) |
| 1374 | return error; | 1396 | return error; |
| 1375 | } | 1397 | if (may_wait) |
| 1398 | wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, | ||
| 1399 | nfs_wait_bit_killable, | ||
| 1400 | TASK_KILLABLE); | ||
| 1401 | } else | ||
| 1402 | nfs_commit_clear_lock(NFS_I(inode)); | ||
| 1403 | out: | ||
| 1376 | return res; | 1404 | return res; |
| 1377 | } | 1405 | } |
| 1378 | 1406 | ||
| @@ -1444,6 +1472,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) | |||
| 1444 | 1472 | ||
| 1445 | BUG_ON(!PageLocked(page)); | 1473 | BUG_ON(!PageLocked(page)); |
| 1446 | for (;;) { | 1474 | for (;;) { |
| 1475 | wait_on_page_writeback(page); | ||
| 1447 | req = nfs_page_find_request(page); | 1476 | req = nfs_page_find_request(page); |
| 1448 | if (req == NULL) | 1477 | if (req == NULL) |
| 1449 | break; | 1478 | break; |
| @@ -1478,30 +1507,18 @@ int nfs_wb_page(struct inode *inode, struct page *page) | |||
| 1478 | .range_start = range_start, | 1507 | .range_start = range_start, |
| 1479 | .range_end = range_end, | 1508 | .range_end = range_end, |
| 1480 | }; | 1509 | }; |
| 1481 | struct nfs_page *req; | ||
| 1482 | int need_commit; | ||
| 1483 | int ret; | 1510 | int ret; |
| 1484 | 1511 | ||
| 1485 | while(PagePrivate(page)) { | 1512 | while(PagePrivate(page)) { |
| 1513 | wait_on_page_writeback(page); | ||
| 1486 | if (clear_page_dirty_for_io(page)) { | 1514 | if (clear_page_dirty_for_io(page)) { |
| 1487 | ret = nfs_writepage_locked(page, &wbc); | 1515 | ret = nfs_writepage_locked(page, &wbc); |
| 1488 | if (ret < 0) | 1516 | if (ret < 0) |
| 1489 | goto out_error; | 1517 | goto out_error; |
| 1490 | } | 1518 | } |
| 1491 | req = nfs_find_and_lock_request(page); | 1519 | ret = sync_inode(inode, &wbc); |
| 1492 | if (!req) | 1520 | if (ret < 0) |
| 1493 | break; | ||
| 1494 | if (IS_ERR(req)) { | ||
| 1495 | ret = PTR_ERR(req); | ||
| 1496 | goto out_error; | 1521 | goto out_error; |
| 1497 | } | ||
| 1498 | need_commit = test_bit(PG_CLEAN, &req->wb_flags); | ||
| 1499 | nfs_clear_page_tag_locked(req); | ||
| 1500 | if (need_commit) { | ||
| 1501 | ret = nfs_commit_inode(inode, FLUSH_SYNC); | ||
| 1502 | if (ret < 0) | ||
| 1503 | goto out_error; | ||
| 1504 | } | ||
| 1505 | } | 1522 | } |
| 1506 | return 0; | 1523 | return 0; |
| 1507 | out_error: | 1524 | out_error: |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index e1703175ee28..34ccf815ea8a 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -161,10 +161,10 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) | |||
| 161 | argp->p = page_address(argp->pagelist[0]); | 161 | argp->p = page_address(argp->pagelist[0]); |
| 162 | argp->pagelist++; | 162 | argp->pagelist++; |
| 163 | if (argp->pagelen < PAGE_SIZE) { | 163 | if (argp->pagelen < PAGE_SIZE) { |
| 164 | argp->end = p + (argp->pagelen>>2); | 164 | argp->end = argp->p + (argp->pagelen>>2); |
| 165 | argp->pagelen = 0; | 165 | argp->pagelen = 0; |
| 166 | } else { | 166 | } else { |
| 167 | argp->end = p + (PAGE_SIZE>>2); | 167 | argp->end = argp->p + (PAGE_SIZE>>2); |
| 168 | argp->pagelen -= PAGE_SIZE; | 168 | argp->pagelen -= PAGE_SIZE; |
| 169 | } | 169 | } |
| 170 | memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); | 170 | memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); |
| @@ -1426,10 +1426,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
| 1426 | argp->p = page_address(argp->pagelist[0]); | 1426 | argp->p = page_address(argp->pagelist[0]); |
| 1427 | argp->pagelist++; | 1427 | argp->pagelist++; |
| 1428 | if (argp->pagelen < PAGE_SIZE) { | 1428 | if (argp->pagelen < PAGE_SIZE) { |
| 1429 | argp->end = p + (argp->pagelen>>2); | 1429 | argp->end = argp->p + (argp->pagelen>>2); |
| 1430 | argp->pagelen = 0; | 1430 | argp->pagelen = 0; |
| 1431 | } else { | 1431 | } else { |
| 1432 | argp->end = p + (PAGE_SIZE>>2); | 1432 | argp->end = argp->p + (PAGE_SIZE>>2); |
| 1433 | argp->pagelen -= PAGE_SIZE; | 1433 | argp->pagelen -= PAGE_SIZE; |
| 1434 | } | 1434 | } |
| 1435 | } | 1435 | } |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 0cdbc5e7655a..48145f505a6a 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
| @@ -749,6 +749,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
| 749 | sb->s_export_op = &nilfs_export_ops; | 749 | sb->s_export_op = &nilfs_export_ops; |
| 750 | sb->s_root = NULL; | 750 | sb->s_root = NULL; |
| 751 | sb->s_time_gran = 1; | 751 | sb->s_time_gran = 1; |
| 752 | sb->s_bdi = nilfs->ns_bdi; | ||
| 752 | 753 | ||
| 753 | err = load_nilfs(nilfs, sbi); | 754 | err = load_nilfs(nilfs, sbi); |
| 754 | if (err) | 755 | if (err) |
diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig index 3e56dbffe729..b3a159b21cfd 100644 --- a/fs/notify/inotify/Kconfig +++ b/fs/notify/inotify/Kconfig | |||
| @@ -15,6 +15,7 @@ config INOTIFY | |||
| 15 | 15 | ||
| 16 | config INOTIFY_USER | 16 | config INOTIFY_USER |
| 17 | bool "Inotify support for userspace" | 17 | bool "Inotify support for userspace" |
| 18 | select ANON_INODES | ||
| 18 | select FSNOTIFY | 19 | select FSNOTIFY |
| 19 | default y | 20 | default y |
| 20 | ---help--- | 21 | ---help--- |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 7621db800a74..8418fcc0a6ab 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -2909,7 +2909,7 @@ out_no_task: | |||
| 2909 | */ | 2909 | */ |
| 2910 | static const struct pid_entry tid_base_stuff[] = { | 2910 | static const struct pid_entry tid_base_stuff[] = { |
| 2911 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), | 2911 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), |
| 2912 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fd_operations), | 2912 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), |
| 2913 | REG("environ", S_IRUSR, proc_environ_operations), | 2913 | REG("environ", S_IRUSR, proc_environ_operations), |
| 2914 | INF("auxv", S_IRUSR, proc_pid_auxv), | 2914 | INF("auxv", S_IRUSR, proc_pid_auxv), |
| 2915 | ONE("status", S_IRUGO, proc_pid_status), | 2915 | ONE("status", S_IRUGO, proc_pid_status), |
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index f8a6075abf50..07930449a958 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
| @@ -46,8 +46,6 @@ static inline bool is_privroot_deh(struct dentry *dir, | |||
| 46 | struct reiserfs_de_head *deh) | 46 | struct reiserfs_de_head *deh) |
| 47 | { | 47 | { |
| 48 | struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root; | 48 | struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root; |
| 49 | if (reiserfs_expose_privroot(dir->d_sb)) | ||
| 50 | return 0; | ||
| 51 | return (dir == dir->d_parent && privroot->d_inode && | 49 | return (dir == dir->d_parent && privroot->d_inode && |
| 52 | deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid); | 50 | deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid); |
| 53 | } | 51 | } |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 4f9586bb7631..e7cc00e636dc 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
| @@ -554,7 +554,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, | |||
| 554 | if (!err && new_size < i_size_read(dentry->d_inode)) { | 554 | if (!err && new_size < i_size_read(dentry->d_inode)) { |
| 555 | struct iattr newattrs = { | 555 | struct iattr newattrs = { |
| 556 | .ia_ctime = current_fs_time(inode->i_sb), | 556 | .ia_ctime = current_fs_time(inode->i_sb), |
| 557 | .ia_size = buffer_size, | 557 | .ia_size = new_size, |
| 558 | .ia_valid = ATTR_SIZE | ATTR_CTIME, | 558 | .ia_valid = ATTR_SIZE | ATTR_CTIME, |
| 559 | }; | 559 | }; |
| 560 | 560 | ||
| @@ -973,21 +973,13 @@ int reiserfs_permission(struct inode *inode, int mask) | |||
| 973 | return generic_permission(inode, mask, NULL); | 973 | return generic_permission(inode, mask, NULL); |
| 974 | } | 974 | } |
| 975 | 975 | ||
| 976 | /* This will catch lookups from the fs root to .reiserfs_priv */ | 976 | static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) |
| 977 | static int | ||
| 978 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) | ||
| 979 | { | 977 | { |
| 980 | struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root; | 978 | return -EPERM; |
| 981 | if (container_of(q1, struct dentry, d_name) == priv_root) | ||
| 982 | return -ENOENT; | ||
| 983 | if (q1->len == name->len && | ||
| 984 | !memcmp(q1->name, name->name, name->len)) | ||
| 985 | return 0; | ||
| 986 | return 1; | ||
| 987 | } | 979 | } |
| 988 | 980 | ||
| 989 | static const struct dentry_operations xattr_lookup_poison_ops = { | 981 | static const struct dentry_operations xattr_lookup_poison_ops = { |
| 990 | .d_compare = xattr_lookup_poison, | 982 | .d_revalidate = xattr_hide_revalidate, |
| 991 | }; | 983 | }; |
| 992 | 984 | ||
| 993 | int reiserfs_lookup_privroot(struct super_block *s) | 985 | int reiserfs_lookup_privroot(struct super_block *s) |
| @@ -1001,8 +993,7 @@ int reiserfs_lookup_privroot(struct super_block *s) | |||
| 1001 | strlen(PRIVROOT_NAME)); | 993 | strlen(PRIVROOT_NAME)); |
| 1002 | if (!IS_ERR(dentry)) { | 994 | if (!IS_ERR(dentry)) { |
| 1003 | REISERFS_SB(s)->priv_root = dentry; | 995 | REISERFS_SB(s)->priv_root = dentry; |
| 1004 | if (!reiserfs_expose_privroot(s)) | 996 | dentry->d_op = &xattr_lookup_poison_ops; |
| 1005 | s->s_root->d_op = &xattr_lookup_poison_ops; | ||
| 1006 | if (dentry->d_inode) | 997 | if (dentry->d_inode) |
| 1007 | dentry->d_inode->i_flags |= S_PRIVATE; | 998 | dentry->d_inode->i_flags |= S_PRIVATE; |
| 1008 | } else | 999 | } else |
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 1c4c8f089970..dfa1d67f8fca 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c | |||
| @@ -479,6 +479,7 @@ smb_put_super(struct super_block *sb) | |||
| 479 | if (server->conn_pid) | 479 | if (server->conn_pid) |
| 480 | kill_pid(server->conn_pid, SIGTERM, 1); | 480 | kill_pid(server->conn_pid, SIGTERM, 1); |
| 481 | 481 | ||
| 482 | bdi_destroy(&server->bdi); | ||
| 482 | kfree(server->ops); | 483 | kfree(server->ops); |
| 483 | smb_unload_nls(server); | 484 | smb_unload_nls(server); |
| 484 | sb->s_fs_info = NULL; | 485 | sb->s_fs_info = NULL; |
| @@ -525,6 +526,11 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
| 525 | if (!server) | 526 | if (!server) |
| 526 | goto out_no_server; | 527 | goto out_no_server; |
| 527 | sb->s_fs_info = server; | 528 | sb->s_fs_info = server; |
| 529 | |||
| 530 | if (bdi_setup_and_register(&server->bdi, "smbfs", BDI_CAP_MAP_COPY)) | ||
| 531 | goto out_bdi; | ||
| 532 | |||
| 533 | sb->s_bdi = &server->bdi; | ||
| 528 | 534 | ||
| 529 | server->super_block = sb; | 535 | server->super_block = sb; |
| 530 | server->mnt = NULL; | 536 | server->mnt = NULL; |
| @@ -624,6 +630,8 @@ out_no_smbiod: | |||
| 624 | out_bad_option: | 630 | out_bad_option: |
| 625 | kfree(mem); | 631 | kfree(mem); |
| 626 | out_no_mem: | 632 | out_no_mem: |
| 633 | bdi_destroy(&server->bdi); | ||
| 634 | out_bdi: | ||
| 627 | if (!server->mnt) | 635 | if (!server->mnt) |
| 628 | printk(KERN_ERR "smb_fill_super: allocation failure\n"); | 636 | printk(KERN_ERR "smb_fill_super: allocation failure\n"); |
| 629 | sb->s_fs_info = NULL; | 637 | sb->s_fs_info = NULL; |
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index 1cb0d81b164b..653c030eb840 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c | |||
| @@ -87,9 +87,8 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, | |||
| 87 | u64 cur_index = index >> msblk->devblksize_log2; | 87 | u64 cur_index = index >> msblk->devblksize_log2; |
| 88 | int bytes, compressed, b = 0, k = 0, page = 0, avail; | 88 | int bytes, compressed, b = 0, k = 0, page = 0, avail; |
| 89 | 89 | ||
| 90 | 90 | bh = kcalloc(((srclength + msblk->devblksize - 1) | |
| 91 | bh = kcalloc((msblk->block_size >> msblk->devblksize_log2) + 1, | 91 | >> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL); |
| 92 | sizeof(*bh), GFP_KERNEL); | ||
| 93 | if (bh == NULL) | 92 | if (bh == NULL) |
| 94 | return -ENOMEM; | 93 | return -ENOMEM; |
| 95 | 94 | ||
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 3550aec2f655..48b6f4a385a6 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c | |||
| @@ -275,7 +275,8 @@ allocate_root: | |||
| 275 | 275 | ||
| 276 | err = squashfs_read_inode(root, root_inode); | 276 | err = squashfs_read_inode(root, root_inode); |
| 277 | if (err) { | 277 | if (err) { |
| 278 | iget_failed(root); | 278 | make_bad_inode(root); |
| 279 | iput(root); | ||
| 279 | goto failed_mount; | 280 | goto failed_mount; |
| 280 | } | 281 | } |
| 281 | insert_inode_hash(root); | 282 | insert_inode_hash(root); |
| @@ -353,6 +354,7 @@ static void squashfs_put_super(struct super_block *sb) | |||
| 353 | kfree(sbi->id_table); | 354 | kfree(sbi->id_table); |
| 354 | kfree(sbi->fragment_index); | 355 | kfree(sbi->fragment_index); |
| 355 | kfree(sbi->meta_index); | 356 | kfree(sbi->meta_index); |
| 357 | kfree(sbi->inode_lookup_table); | ||
| 356 | kfree(sb->s_fs_info); | 358 | kfree(sb->s_fs_info); |
| 357 | sb->s_fs_info = NULL; | 359 | sb->s_fs_info = NULL; |
| 358 | } | 360 | } |
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c index 15a03d0fb9f3..7a603874e483 100644 --- a/fs/squashfs/zlib_wrapper.c +++ b/fs/squashfs/zlib_wrapper.c | |||
| @@ -128,8 +128,9 @@ static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, | |||
| 128 | goto release_mutex; | 128 | goto release_mutex; |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | length = stream->total_out; | ||
| 131 | mutex_unlock(&msblk->read_data_mutex); | 132 | mutex_unlock(&msblk->read_data_mutex); |
| 132 | return stream->total_out; | 133 | return length; |
| 133 | 134 | ||
| 134 | release_mutex: | 135 | release_mutex: |
| 135 | mutex_unlock(&msblk->read_data_mutex); | 136 | mutex_unlock(&msblk->read_data_mutex); |
diff --git a/fs/super.c b/fs/super.c index f35ac6022109..1527e6a0ee35 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/kobject.h> | 37 | #include <linux/kobject.h> |
| 38 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
| 39 | #include <linux/file.h> | 39 | #include <linux/file.h> |
| 40 | #include <linux/backing-dev.h> | ||
| 40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
| 41 | #include "internal.h" | 42 | #include "internal.h" |
| 42 | 43 | ||
| @@ -693,6 +694,7 @@ int set_anon_super(struct super_block *s, void *data) | |||
| 693 | return -EMFILE; | 694 | return -EMFILE; |
| 694 | } | 695 | } |
| 695 | s->s_dev = MKDEV(0, dev & MINORMASK); | 696 | s->s_dev = MKDEV(0, dev & MINORMASK); |
| 697 | s->s_bdi = &noop_backing_dev_info; | ||
| 696 | return 0; | 698 | return 0; |
| 697 | } | 699 | } |
| 698 | 700 | ||
| @@ -954,10 +956,11 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
| 954 | if (error < 0) | 956 | if (error < 0) |
| 955 | goto out_free_secdata; | 957 | goto out_free_secdata; |
| 956 | BUG_ON(!mnt->mnt_sb); | 958 | BUG_ON(!mnt->mnt_sb); |
| 959 | WARN_ON(!mnt->mnt_sb->s_bdi); | ||
| 957 | 960 | ||
| 958 | error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); | 961 | error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); |
| 959 | if (error) | 962 | if (error) |
| 960 | goto out_sb; | 963 | goto out_sb; |
| 961 | 964 | ||
| 962 | /* | 965 | /* |
| 963 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE | 966 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE |
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/pagemap.h> | 14 | #include <linux/pagemap.h> |
| 15 | #include <linux/quotaops.h> | 15 | #include <linux/quotaops.h> |
| 16 | #include <linux/buffer_head.h> | 16 | #include <linux/buffer_head.h> |
| 17 | #include <linux/backing-dev.h> | ||
| 17 | #include "internal.h" | 18 | #include "internal.h" |
| 18 | 19 | ||
| 19 | #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ | 20 | #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ |
| @@ -32,7 +33,7 @@ static int __sync_filesystem(struct super_block *sb, int wait) | |||
| 32 | * This should be safe, as we require bdi backing to actually | 33 | * This should be safe, as we require bdi backing to actually |
| 33 | * write out data in the first place | 34 | * write out data in the first place |
| 34 | */ | 35 | */ |
| 35 | if (!sb->s_bdi) | 36 | if (!sb->s_bdi || sb->s_bdi == &noop_backing_dev_info) |
| 36 | return 0; | 37 | return 0; |
| 37 | 38 | ||
| 38 | if (sb->s_qcop && sb->s_qcop->quota_sync) | 39 | if (sb->s_qcop && sb->s_qcop->quota_sync) |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 52e06b487ced..29f1edca76de 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
| @@ -1209,6 +1209,7 @@ xfs_fs_put_super( | |||
| 1209 | 1209 | ||
| 1210 | xfs_unmountfs(mp); | 1210 | xfs_unmountfs(mp); |
| 1211 | xfs_freesb(mp); | 1211 | xfs_freesb(mp); |
| 1212 | xfs_inode_shrinker_unregister(mp); | ||
| 1212 | xfs_icsb_destroy_counters(mp); | 1213 | xfs_icsb_destroy_counters(mp); |
| 1213 | xfs_close_devices(mp); | 1214 | xfs_close_devices(mp); |
| 1214 | xfs_dmops_put(mp); | 1215 | xfs_dmops_put(mp); |
| @@ -1622,6 +1623,8 @@ xfs_fs_fill_super( | |||
| 1622 | if (error) | 1623 | if (error) |
| 1623 | goto fail_vnrele; | 1624 | goto fail_vnrele; |
| 1624 | 1625 | ||
| 1626 | xfs_inode_shrinker_register(mp); | ||
| 1627 | |||
| 1625 | kfree(mtpt); | 1628 | kfree(mtpt); |
| 1626 | return 0; | 1629 | return 0; |
| 1627 | 1630 | ||
| @@ -1867,6 +1870,7 @@ init_xfs_fs(void) | |||
| 1867 | goto out_cleanup_procfs; | 1870 | goto out_cleanup_procfs; |
| 1868 | 1871 | ||
| 1869 | vfs_initquota(); | 1872 | vfs_initquota(); |
| 1873 | xfs_inode_shrinker_init(); | ||
| 1870 | 1874 | ||
| 1871 | error = register_filesystem(&xfs_fs_type); | 1875 | error = register_filesystem(&xfs_fs_type); |
| 1872 | if (error) | 1876 | if (error) |
| @@ -1894,6 +1898,7 @@ exit_xfs_fs(void) | |||
| 1894 | { | 1898 | { |
| 1895 | vfs_exitquota(); | 1899 | vfs_exitquota(); |
| 1896 | unregister_filesystem(&xfs_fs_type); | 1900 | unregister_filesystem(&xfs_fs_type); |
| 1901 | xfs_inode_shrinker_destroy(); | ||
| 1897 | xfs_sysctl_unregister(); | 1902 | xfs_sysctl_unregister(); |
| 1898 | xfs_cleanup_procfs(); | 1903 | xfs_cleanup_procfs(); |
| 1899 | xfs_buf_terminate(); | 1904 | xfs_buf_terminate(); |
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index fd9698215759..a427c638d909 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
| @@ -95,7 +95,8 @@ xfs_inode_ag_walk( | |||
| 95 | struct xfs_perag *pag, int flags), | 95 | struct xfs_perag *pag, int flags), |
| 96 | int flags, | 96 | int flags, |
| 97 | int tag, | 97 | int tag, |
| 98 | int exclusive) | 98 | int exclusive, |
| 99 | int *nr_to_scan) | ||
| 99 | { | 100 | { |
| 100 | uint32_t first_index; | 101 | uint32_t first_index; |
| 101 | int last_error = 0; | 102 | int last_error = 0; |
| @@ -134,7 +135,7 @@ restart: | |||
| 134 | if (error == EFSCORRUPTED) | 135 | if (error == EFSCORRUPTED) |
| 135 | break; | 136 | break; |
| 136 | 137 | ||
| 137 | } while (1); | 138 | } while ((*nr_to_scan)--); |
| 138 | 139 | ||
| 139 | if (skipped) { | 140 | if (skipped) { |
| 140 | delay(1); | 141 | delay(1); |
| @@ -150,12 +151,15 @@ xfs_inode_ag_iterator( | |||
| 150 | struct xfs_perag *pag, int flags), | 151 | struct xfs_perag *pag, int flags), |
| 151 | int flags, | 152 | int flags, |
| 152 | int tag, | 153 | int tag, |
| 153 | int exclusive) | 154 | int exclusive, |
| 155 | int *nr_to_scan) | ||
| 154 | { | 156 | { |
| 155 | int error = 0; | 157 | int error = 0; |
| 156 | int last_error = 0; | 158 | int last_error = 0; |
| 157 | xfs_agnumber_t ag; | 159 | xfs_agnumber_t ag; |
| 160 | int nr; | ||
| 158 | 161 | ||
| 162 | nr = nr_to_scan ? *nr_to_scan : INT_MAX; | ||
| 159 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | 163 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { |
| 160 | struct xfs_perag *pag; | 164 | struct xfs_perag *pag; |
| 161 | 165 | ||
| @@ -165,14 +169,18 @@ xfs_inode_ag_iterator( | |||
| 165 | continue; | 169 | continue; |
| 166 | } | 170 | } |
| 167 | error = xfs_inode_ag_walk(mp, pag, execute, flags, tag, | 171 | error = xfs_inode_ag_walk(mp, pag, execute, flags, tag, |
| 168 | exclusive); | 172 | exclusive, &nr); |
| 169 | xfs_perag_put(pag); | 173 | xfs_perag_put(pag); |
| 170 | if (error) { | 174 | if (error) { |
| 171 | last_error = error; | 175 | last_error = error; |
| 172 | if (error == EFSCORRUPTED) | 176 | if (error == EFSCORRUPTED) |
| 173 | break; | 177 | break; |
| 174 | } | 178 | } |
| 179 | if (nr <= 0) | ||
| 180 | break; | ||
| 175 | } | 181 | } |
| 182 | if (nr_to_scan) | ||
| 183 | *nr_to_scan = nr; | ||
| 176 | return XFS_ERROR(last_error); | 184 | return XFS_ERROR(last_error); |
| 177 | } | 185 | } |
| 178 | 186 | ||
| @@ -291,7 +299,7 @@ xfs_sync_data( | |||
| 291 | ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0); | 299 | ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0); |
| 292 | 300 | ||
| 293 | error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags, | 301 | error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags, |
| 294 | XFS_ICI_NO_TAG, 0); | 302 | XFS_ICI_NO_TAG, 0, NULL); |
| 295 | if (error) | 303 | if (error) |
| 296 | return XFS_ERROR(error); | 304 | return XFS_ERROR(error); |
| 297 | 305 | ||
| @@ -310,7 +318,7 @@ xfs_sync_attr( | |||
| 310 | ASSERT((flags & ~SYNC_WAIT) == 0); | 318 | ASSERT((flags & ~SYNC_WAIT) == 0); |
| 311 | 319 | ||
| 312 | return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags, | 320 | return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags, |
| 313 | XFS_ICI_NO_TAG, 0); | 321 | XFS_ICI_NO_TAG, 0, NULL); |
| 314 | } | 322 | } |
| 315 | 323 | ||
| 316 | STATIC int | 324 | STATIC int |
| @@ -673,6 +681,7 @@ __xfs_inode_set_reclaim_tag( | |||
| 673 | radix_tree_tag_set(&pag->pag_ici_root, | 681 | radix_tree_tag_set(&pag->pag_ici_root, |
| 674 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), | 682 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), |
| 675 | XFS_ICI_RECLAIM_TAG); | 683 | XFS_ICI_RECLAIM_TAG); |
| 684 | pag->pag_ici_reclaimable++; | ||
| 676 | } | 685 | } |
| 677 | 686 | ||
| 678 | /* | 687 | /* |
| @@ -705,6 +714,7 @@ __xfs_inode_clear_reclaim_tag( | |||
| 705 | { | 714 | { |
| 706 | radix_tree_tag_clear(&pag->pag_ici_root, | 715 | radix_tree_tag_clear(&pag->pag_ici_root, |
| 707 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | 716 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); |
| 717 | pag->pag_ici_reclaimable--; | ||
| 708 | } | 718 | } |
| 709 | 719 | ||
| 710 | /* | 720 | /* |
| @@ -854,5 +864,93 @@ xfs_reclaim_inodes( | |||
| 854 | int mode) | 864 | int mode) |
| 855 | { | 865 | { |
| 856 | return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode, | 866 | return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode, |
| 857 | XFS_ICI_RECLAIM_TAG, 1); | 867 | XFS_ICI_RECLAIM_TAG, 1, NULL); |
| 868 | } | ||
| 869 | |||
| 870 | /* | ||
| 871 | * Shrinker infrastructure. | ||
| 872 | * | ||
| 873 | * This is all far more complex than it needs to be. It adds a global list of | ||
| 874 | * mounts because the shrinkers can only call a global context. We need to make | ||
| 875 | * the shrinkers pass a context to avoid the need for global state. | ||
| 876 | */ | ||
| 877 | static LIST_HEAD(xfs_mount_list); | ||
| 878 | static struct rw_semaphore xfs_mount_list_lock; | ||
| 879 | |||
| 880 | static int | ||
| 881 | xfs_reclaim_inode_shrink( | ||
| 882 | int nr_to_scan, | ||
| 883 | gfp_t gfp_mask) | ||
| 884 | { | ||
| 885 | struct xfs_mount *mp; | ||
| 886 | struct xfs_perag *pag; | ||
| 887 | xfs_agnumber_t ag; | ||
| 888 | int reclaimable = 0; | ||
| 889 | |||
| 890 | if (nr_to_scan) { | ||
| 891 | if (!(gfp_mask & __GFP_FS)) | ||
| 892 | return -1; | ||
| 893 | |||
| 894 | down_read(&xfs_mount_list_lock); | ||
| 895 | list_for_each_entry(mp, &xfs_mount_list, m_mplist) { | ||
| 896 | xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0, | ||
| 897 | XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan); | ||
| 898 | if (nr_to_scan <= 0) | ||
| 899 | break; | ||
| 900 | } | ||
| 901 | up_read(&xfs_mount_list_lock); | ||
| 902 | } | ||
| 903 | |||
| 904 | down_read(&xfs_mount_list_lock); | ||
| 905 | list_for_each_entry(mp, &xfs_mount_list, m_mplist) { | ||
| 906 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | ||
| 907 | |||
| 908 | pag = xfs_perag_get(mp, ag); | ||
| 909 | if (!pag->pag_ici_init) { | ||
| 910 | xfs_perag_put(pag); | ||
| 911 | continue; | ||
| 912 | } | ||
| 913 | reclaimable += pag->pag_ici_reclaimable; | ||
| 914 | xfs_perag_put(pag); | ||
| 915 | } | ||
| 916 | } | ||
| 917 | up_read(&xfs_mount_list_lock); | ||
| 918 | return reclaimable; | ||
| 919 | } | ||
| 920 | |||
| 921 | static struct shrinker xfs_inode_shrinker = { | ||
| 922 | .shrink = xfs_reclaim_inode_shrink, | ||
| 923 | .seeks = DEFAULT_SEEKS, | ||
| 924 | }; | ||
| 925 | |||
| 926 | void __init | ||
| 927 | xfs_inode_shrinker_init(void) | ||
| 928 | { | ||
| 929 | init_rwsem(&xfs_mount_list_lock); | ||
| 930 | register_shrinker(&xfs_inode_shrinker); | ||
| 931 | } | ||
| 932 | |||
| 933 | void | ||
| 934 | xfs_inode_shrinker_destroy(void) | ||
| 935 | { | ||
| 936 | ASSERT(list_empty(&xfs_mount_list)); | ||
| 937 | unregister_shrinker(&xfs_inode_shrinker); | ||
| 938 | } | ||
| 939 | |||
| 940 | void | ||
| 941 | xfs_inode_shrinker_register( | ||
| 942 | struct xfs_mount *mp) | ||
| 943 | { | ||
| 944 | down_write(&xfs_mount_list_lock); | ||
| 945 | list_add_tail(&mp->m_mplist, &xfs_mount_list); | ||
| 946 | up_write(&xfs_mount_list_lock); | ||
| 947 | } | ||
| 948 | |||
| 949 | void | ||
| 950 | xfs_inode_shrinker_unregister( | ||
| 951 | struct xfs_mount *mp) | ||
| 952 | { | ||
| 953 | down_write(&xfs_mount_list_lock); | ||
| 954 | list_del(&mp->m_mplist); | ||
| 955 | up_write(&xfs_mount_list_lock); | ||
| 858 | } | 956 | } |
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index d480c346cabb..cdcbaaca9880 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
| @@ -53,6 +53,11 @@ void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag, | |||
| 53 | int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag); | 53 | int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag); |
| 54 | int xfs_inode_ag_iterator(struct xfs_mount *mp, | 54 | int xfs_inode_ag_iterator(struct xfs_mount *mp, |
| 55 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), | 55 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), |
| 56 | int flags, int tag, int write_lock); | 56 | int flags, int tag, int write_lock, int *nr_to_scan); |
| 57 | |||
| 58 | void xfs_inode_shrinker_init(void); | ||
| 59 | void xfs_inode_shrinker_destroy(void); | ||
| 60 | void xfs_inode_shrinker_register(struct xfs_mount *mp); | ||
| 61 | void xfs_inode_shrinker_unregister(struct xfs_mount *mp); | ||
| 57 | 62 | ||
| 58 | #endif | 63 | #endif |
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 5d0ee8d492db..50bee07d6b0e 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
| @@ -891,7 +891,8 @@ xfs_qm_dqrele_all_inodes( | |||
| 891 | uint flags) | 891 | uint flags) |
| 892 | { | 892 | { |
| 893 | ASSERT(mp->m_quotainfo); | 893 | ASSERT(mp->m_quotainfo); |
| 894 | xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, XFS_ICI_NO_TAG, 0); | 894 | xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, |
| 895 | XFS_ICI_NO_TAG, 0, NULL); | ||
| 895 | } | 896 | } |
| 896 | 897 | ||
| 897 | /*------------------------------------------------------------------------*/ | 898 | /*------------------------------------------------------------------------*/ |
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h index b1a5a1ff88ea..abb8222b88c9 100644 --- a/fs/xfs/xfs_ag.h +++ b/fs/xfs/xfs_ag.h | |||
| @@ -223,6 +223,7 @@ typedef struct xfs_perag { | |||
| 223 | int pag_ici_init; /* incore inode cache initialised */ | 223 | int pag_ici_init; /* incore inode cache initialised */ |
| 224 | rwlock_t pag_ici_lock; /* incore inode lock */ | 224 | rwlock_t pag_ici_lock; /* incore inode lock */ |
| 225 | struct radix_tree_root pag_ici_root; /* incore inode cache root */ | 225 | struct radix_tree_root pag_ici_root; /* incore inode cache root */ |
| 226 | int pag_ici_reclaimable; /* reclaimable inodes */ | ||
| 226 | #endif | 227 | #endif |
| 227 | int pagb_count; /* pagb slots in use */ | 228 | int pagb_count; /* pagb slots in use */ |
| 228 | xfs_perag_busy_t pagb_list[XFS_PAGB_NUM_SLOTS]; /* unstable blocks */ | 229 | xfs_perag_busy_t pagb_list[XFS_PAGB_NUM_SLOTS]; /* unstable blocks */ |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index cd27c9d6c71f..5bba29a07812 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
| @@ -177,16 +177,26 @@ xfs_swap_extents_check_format( | |||
| 177 | XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > tip->i_df.if_ext_max) | 177 | XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > tip->i_df.if_ext_max) |
| 178 | return EINVAL; | 178 | return EINVAL; |
| 179 | 179 | ||
| 180 | /* Check root block of temp in btree form to max in target */ | 180 | /* |
| 181 | * If we are in a btree format, check that the temp root block will fit | ||
| 182 | * in the target and that it has enough extents to be in btree format | ||
| 183 | * in the target. | ||
| 184 | * | ||
| 185 | * Note that we have to be careful to allow btree->extent conversions | ||
| 186 | * (a common defrag case) which will occur when the temp inode is in | ||
| 187 | * extent format... | ||
| 188 | */ | ||
| 181 | if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE && | 189 | if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE && |
| 182 | XFS_IFORK_BOFF(ip) && | 190 | ((XFS_IFORK_BOFF(ip) && |
| 183 | tip->i_df.if_broot_bytes > XFS_IFORK_BOFF(ip)) | 191 | tip->i_df.if_broot_bytes > XFS_IFORK_BOFF(ip)) || |
| 192 | XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <= ip->i_df.if_ext_max)) | ||
| 184 | return EINVAL; | 193 | return EINVAL; |
| 185 | 194 | ||
| 186 | /* Check root block of target in btree form to max in temp */ | 195 | /* Reciprocal target->temp btree format checks */ |
| 187 | if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE && | 196 | if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE && |
| 188 | XFS_IFORK_BOFF(tip) && | 197 | ((XFS_IFORK_BOFF(tip) && |
| 189 | ip->i_df.if_broot_bytes > XFS_IFORK_BOFF(tip)) | 198 | ip->i_df.if_broot_bytes > XFS_IFORK_BOFF(tip)) || |
| 199 | XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <= tip->i_df.if_ext_max)) | ||
| 190 | return EINVAL; | 200 | return EINVAL; |
| 191 | 201 | ||
| 192 | return 0; | 202 | return 0; |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 4fa0bc7b983e..9ff48a16a7ee 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
| @@ -259,6 +259,7 @@ typedef struct xfs_mount { | |||
| 259 | wait_queue_head_t m_wait_single_sync_task; | 259 | wait_queue_head_t m_wait_single_sync_task; |
| 260 | __int64_t m_update_flags; /* sb flags we need to update | 260 | __int64_t m_update_flags; /* sb flags we need to update |
| 261 | on the next remount,rw */ | 261 | on the next remount,rw */ |
| 262 | struct list_head m_mplist; /* inode shrinker mount list */ | ||
| 262 | } xfs_mount_t; | 263 | } xfs_mount_t; |
| 263 | 264 | ||
| 264 | /* | 265 | /* |
