diff options
Diffstat (limited to 'fs')
49 files changed, 341 insertions, 194 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/mntpt.c b/fs/afs/mntpt.c index 5e813a816ce4..b3feddc4f7d6 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
| @@ -138,9 +138,9 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) | |||
| 138 | { | 138 | { |
| 139 | struct afs_super_info *super; | 139 | struct afs_super_info *super; |
| 140 | struct vfsmount *mnt; | 140 | struct vfsmount *mnt; |
| 141 | struct page *page = NULL; | 141 | struct page *page; |
| 142 | size_t size; | 142 | size_t size; |
| 143 | char *buf, *devname = NULL, *options = NULL; | 143 | char *buf, *devname, *options; |
| 144 | int ret; | 144 | int ret; |
| 145 | 145 | ||
| 146 | _enter("{%s}", mntpt->d_name.name); | 146 | _enter("{%s}", mntpt->d_name.name); |
| @@ -150,22 +150,22 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) | |||
| 150 | ret = -EINVAL; | 150 | ret = -EINVAL; |
| 151 | size = mntpt->d_inode->i_size; | 151 | size = mntpt->d_inode->i_size; |
| 152 | if (size > PAGE_SIZE - 1) | 152 | if (size > PAGE_SIZE - 1) |
| 153 | goto error; | 153 | goto error_no_devname; |
| 154 | 154 | ||
| 155 | ret = -ENOMEM; | 155 | ret = -ENOMEM; |
| 156 | devname = (char *) get_zeroed_page(GFP_KERNEL); | 156 | devname = (char *) get_zeroed_page(GFP_KERNEL); |
| 157 | if (!devname) | 157 | if (!devname) |
| 158 | goto error; | 158 | goto error_no_devname; |
| 159 | 159 | ||
| 160 | options = (char *) get_zeroed_page(GFP_KERNEL); | 160 | options = (char *) get_zeroed_page(GFP_KERNEL); |
| 161 | if (!options) | 161 | if (!options) |
| 162 | goto error; | 162 | goto error_no_options; |
| 163 | 163 | ||
| 164 | /* read the contents of the AFS special symlink */ | 164 | /* read the contents of the AFS special symlink */ |
| 165 | page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL); | 165 | page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL); |
| 166 | if (IS_ERR(page)) { | 166 | if (IS_ERR(page)) { |
| 167 | ret = PTR_ERR(page); | 167 | ret = PTR_ERR(page); |
| 168 | goto error; | 168 | goto error_no_page; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | ret = -EIO; | 171 | ret = -EIO; |
| @@ -196,12 +196,12 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) | |||
| 196 | return mnt; | 196 | return mnt; |
| 197 | 197 | ||
| 198 | error: | 198 | error: |
| 199 | if (page) | 199 | page_cache_release(page); |
| 200 | page_cache_release(page); | 200 | error_no_page: |
| 201 | if (devname) | 201 | free_page((unsigned long) options); |
| 202 | free_page((unsigned long) devname); | 202 | error_no_options: |
| 203 | if (options) | 203 | free_page((unsigned long) devname); |
| 204 | free_page((unsigned long) options); | 204 | error_no_devname: |
| 205 | _leave(" = %d", ret); | 205 | _leave(" = %d", ret); |
| 206 | return ERR_PTR(ret); | 206 | return ERR_PTR(ret); |
| 207 | } | 207 | } |
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/binfmt_flat.c b/fs/binfmt_flat.c index e0e769bdca59..49566c1687d8 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
| @@ -355,7 +355,7 @@ calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp) | |||
| 355 | 355 | ||
| 356 | if (!flat_reloc_valid(r, start_brk - start_data + text_len)) { | 356 | if (!flat_reloc_valid(r, start_brk - start_data + text_len)) { |
| 357 | printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)", | 357 | printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)", |
| 358 | (int) r,(int)(start_brk-start_code),(int)text_len); | 358 | (int) r,(int)(start_brk-start_data+text_len),(int)text_len); |
| 359 | goto failed; | 359 | goto failed; |
| 360 | } | 360 | } |
| 361 | 361 | ||
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/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/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..54373278a353 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 |
| @@ -92,6 +93,7 @@ struct exofs_sb_info { | |||
| 92 | struct exofs_layout layout; /* Default files layout, | 93 | struct exofs_layout layout; /* Default files layout, |
| 93 | * contains the variable osd_dev | 94 | * contains the variable osd_dev |
| 94 | * array. Keep last */ | 95 | * array. Keep last */ |
| 96 | struct backing_dev_info bdi; | ||
| 95 | struct osd_dev *_min_one_dev[1]; /* Place holder for one dev */ | 97 | struct osd_dev *_min_one_dev[1]; /* Place holder for one dev */ |
| 96 | }; | 98 | }; |
| 97 | 99 | ||
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/jfs/inode.c b/fs/jfs/inode.c index 9dd126276c9f..ed9ba6fe04f5 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c | |||
| @@ -61,7 +61,7 @@ struct inode *jfs_iget(struct super_block *sb, unsigned long ino) | |||
| 61 | inode->i_op = &page_symlink_inode_operations; | 61 | inode->i_op = &page_symlink_inode_operations; |
| 62 | inode->i_mapping->a_ops = &jfs_aops; | 62 | inode->i_mapping->a_ops = &jfs_aops; |
| 63 | } else { | 63 | } else { |
| 64 | inode->i_op = &jfs_symlink_inode_operations; | 64 | inode->i_op = &jfs_fast_symlink_inode_operations; |
| 65 | /* | 65 | /* |
| 66 | * The inline data should be null-terminated, but | 66 | * The inline data should be null-terminated, but |
| 67 | * don't let on-disk corruption crash the kernel | 67 | * don't let on-disk corruption crash the kernel |
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 6c4dfcbf3f55..9e2f6a721668 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c | |||
| @@ -196,7 +196,7 @@ int dbMount(struct inode *ipbmap) | |||
| 196 | bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag); | 196 | bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag); |
| 197 | bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref); | 197 | bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref); |
| 198 | bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel); | 198 | bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel); |
| 199 | bmp->db_agheigth = le32_to_cpu(dbmp_le->dn_agheigth); | 199 | bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight); |
| 200 | bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth); | 200 | bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth); |
| 201 | bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart); | 201 | bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart); |
| 202 | bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size); | 202 | bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size); |
| @@ -288,7 +288,7 @@ int dbSync(struct inode *ipbmap) | |||
| 288 | dbmp_le->dn_maxag = cpu_to_le32(bmp->db_maxag); | 288 | dbmp_le->dn_maxag = cpu_to_le32(bmp->db_maxag); |
| 289 | dbmp_le->dn_agpref = cpu_to_le32(bmp->db_agpref); | 289 | dbmp_le->dn_agpref = cpu_to_le32(bmp->db_agpref); |
| 290 | dbmp_le->dn_aglevel = cpu_to_le32(bmp->db_aglevel); | 290 | dbmp_le->dn_aglevel = cpu_to_le32(bmp->db_aglevel); |
| 291 | dbmp_le->dn_agheigth = cpu_to_le32(bmp->db_agheigth); | 291 | dbmp_le->dn_agheight = cpu_to_le32(bmp->db_agheight); |
| 292 | dbmp_le->dn_agwidth = cpu_to_le32(bmp->db_agwidth); | 292 | dbmp_le->dn_agwidth = cpu_to_le32(bmp->db_agwidth); |
| 293 | dbmp_le->dn_agstart = cpu_to_le32(bmp->db_agstart); | 293 | dbmp_le->dn_agstart = cpu_to_le32(bmp->db_agstart); |
| 294 | dbmp_le->dn_agl2size = cpu_to_le32(bmp->db_agl2size); | 294 | dbmp_le->dn_agl2size = cpu_to_le32(bmp->db_agl2size); |
| @@ -1441,7 +1441,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) | |||
| 1441 | * tree index of this allocation group within the control page. | 1441 | * tree index of this allocation group within the control page. |
| 1442 | */ | 1442 | */ |
| 1443 | agperlev = | 1443 | agperlev = |
| 1444 | (1 << (L2LPERCTL - (bmp->db_agheigth << 1))) / bmp->db_agwidth; | 1444 | (1 << (L2LPERCTL - (bmp->db_agheight << 1))) / bmp->db_agwidth; |
| 1445 | ti = bmp->db_agstart + bmp->db_agwidth * (agno & (agperlev - 1)); | 1445 | ti = bmp->db_agstart + bmp->db_agwidth * (agno & (agperlev - 1)); |
| 1446 | 1446 | ||
| 1447 | /* dmap control page trees fan-out by 4 and a single allocation | 1447 | /* dmap control page trees fan-out by 4 and a single allocation |
| @@ -1460,7 +1460,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) | |||
| 1460 | * the subtree to find the leftmost leaf that describes this | 1460 | * the subtree to find the leftmost leaf that describes this |
| 1461 | * free space. | 1461 | * free space. |
| 1462 | */ | 1462 | */ |
| 1463 | for (k = bmp->db_agheigth; k > 0; k--) { | 1463 | for (k = bmp->db_agheight; k > 0; k--) { |
| 1464 | for (n = 0, m = (ti << 2) + 1; n < 4; n++) { | 1464 | for (n = 0, m = (ti << 2) + 1; n < 4; n++) { |
| 1465 | if (l2nb <= dcp->stree[m + n]) { | 1465 | if (l2nb <= dcp->stree[m + n]) { |
| 1466 | ti = m + n; | 1466 | ti = m + n; |
| @@ -3607,7 +3607,7 @@ void dbFinalizeBmap(struct inode *ipbmap) | |||
| 3607 | } | 3607 | } |
| 3608 | 3608 | ||
| 3609 | /* | 3609 | /* |
| 3610 | * compute db_aglevel, db_agheigth, db_width, db_agstart: | 3610 | * compute db_aglevel, db_agheight, db_width, db_agstart: |
| 3611 | * an ag is covered in aglevel dmapctl summary tree, | 3611 | * an ag is covered in aglevel dmapctl summary tree, |
| 3612 | * at agheight level height (from leaf) with agwidth number of nodes | 3612 | * at agheight level height (from leaf) with agwidth number of nodes |
| 3613 | * each, which starts at agstart index node of the smmary tree node | 3613 | * each, which starts at agstart index node of the smmary tree node |
| @@ -3616,9 +3616,9 @@ void dbFinalizeBmap(struct inode *ipbmap) | |||
| 3616 | bmp->db_aglevel = BMAPSZTOLEV(bmp->db_agsize); | 3616 | bmp->db_aglevel = BMAPSZTOLEV(bmp->db_agsize); |
| 3617 | l2nl = | 3617 | l2nl = |
| 3618 | bmp->db_agl2size - (L2BPERDMAP + bmp->db_aglevel * L2LPERCTL); | 3618 | bmp->db_agl2size - (L2BPERDMAP + bmp->db_aglevel * L2LPERCTL); |
| 3619 | bmp->db_agheigth = l2nl >> 1; | 3619 | bmp->db_agheight = l2nl >> 1; |
| 3620 | bmp->db_agwidth = 1 << (l2nl - (bmp->db_agheigth << 1)); | 3620 | bmp->db_agwidth = 1 << (l2nl - (bmp->db_agheight << 1)); |
| 3621 | for (i = 5 - bmp->db_agheigth, bmp->db_agstart = 0, n = 1; i > 0; | 3621 | for (i = 5 - bmp->db_agheight, bmp->db_agstart = 0, n = 1; i > 0; |
| 3622 | i--) { | 3622 | i--) { |
| 3623 | bmp->db_agstart += n; | 3623 | bmp->db_agstart += n; |
| 3624 | n <<= 2; | 3624 | n <<= 2; |
diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h index 1a6eb41569bc..6dcb906c55d8 100644 --- a/fs/jfs/jfs_dmap.h +++ b/fs/jfs/jfs_dmap.h | |||
| @@ -210,7 +210,7 @@ struct dbmap_disk { | |||
| 210 | __le32 dn_maxag; /* 4: max active alloc group number */ | 210 | __le32 dn_maxag; /* 4: max active alloc group number */ |
| 211 | __le32 dn_agpref; /* 4: preferred alloc group (hint) */ | 211 | __le32 dn_agpref; /* 4: preferred alloc group (hint) */ |
| 212 | __le32 dn_aglevel; /* 4: dmapctl level holding the AG */ | 212 | __le32 dn_aglevel; /* 4: dmapctl level holding the AG */ |
| 213 | __le32 dn_agheigth; /* 4: height in dmapctl of the AG */ | 213 | __le32 dn_agheight; /* 4: height in dmapctl of the AG */ |
| 214 | __le32 dn_agwidth; /* 4: width in dmapctl of the AG */ | 214 | __le32 dn_agwidth; /* 4: width in dmapctl of the AG */ |
| 215 | __le32 dn_agstart; /* 4: start tree index at AG height */ | 215 | __le32 dn_agstart; /* 4: start tree index at AG height */ |
| 216 | __le32 dn_agl2size; /* 4: l2 num of blks per alloc group */ | 216 | __le32 dn_agl2size; /* 4: l2 num of blks per alloc group */ |
| @@ -229,7 +229,7 @@ struct dbmap { | |||
| 229 | int dn_maxag; /* max active alloc group number */ | 229 | int dn_maxag; /* max active alloc group number */ |
| 230 | int dn_agpref; /* preferred alloc group (hint) */ | 230 | int dn_agpref; /* preferred alloc group (hint) */ |
| 231 | int dn_aglevel; /* dmapctl level holding the AG */ | 231 | int dn_aglevel; /* dmapctl level holding the AG */ |
| 232 | int dn_agheigth; /* height in dmapctl of the AG */ | 232 | int dn_agheight; /* height in dmapctl of the AG */ |
| 233 | int dn_agwidth; /* width in dmapctl of the AG */ | 233 | int dn_agwidth; /* width in dmapctl of the AG */ |
| 234 | int dn_agstart; /* start tree index at AG height */ | 234 | int dn_agstart; /* start tree index at AG height */ |
| 235 | int dn_agl2size; /* l2 num of blks per alloc group */ | 235 | int dn_agl2size; /* l2 num of blks per alloc group */ |
| @@ -255,7 +255,7 @@ struct bmap { | |||
| 255 | #define db_agsize db_bmap.dn_agsize | 255 | #define db_agsize db_bmap.dn_agsize |
| 256 | #define db_agl2size db_bmap.dn_agl2size | 256 | #define db_agl2size db_bmap.dn_agl2size |
| 257 | #define db_agwidth db_bmap.dn_agwidth | 257 | #define db_agwidth db_bmap.dn_agwidth |
| 258 | #define db_agheigth db_bmap.dn_agheigth | 258 | #define db_agheight db_bmap.dn_agheight |
| 259 | #define db_agstart db_bmap.dn_agstart | 259 | #define db_agstart db_bmap.dn_agstart |
| 260 | #define db_numag db_bmap.dn_numag | 260 | #define db_numag db_bmap.dn_numag |
| 261 | #define db_maxlevel db_bmap.dn_maxlevel | 261 | #define db_maxlevel db_bmap.dn_maxlevel |
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index 79e2c79661df..9e6bda30a6e8 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h | |||
| @@ -48,5 +48,6 @@ extern const struct file_operations jfs_dir_operations; | |||
| 48 | extern const struct inode_operations jfs_file_inode_operations; | 48 | extern const struct inode_operations jfs_file_inode_operations; |
| 49 | extern const struct file_operations jfs_file_operations; | 49 | extern const struct file_operations jfs_file_operations; |
| 50 | extern const struct inode_operations jfs_symlink_inode_operations; | 50 | extern const struct inode_operations jfs_symlink_inode_operations; |
| 51 | extern const struct inode_operations jfs_fast_symlink_inode_operations; | ||
| 51 | extern const struct dentry_operations jfs_ci_dentry_operations; | 52 | extern const struct dentry_operations jfs_ci_dentry_operations; |
| 52 | #endif /* _H_JFS_INODE */ | 53 | #endif /* _H_JFS_INODE */ |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 4a3e9f39c21d..a9cf8e8675be 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
| @@ -956,7 +956,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
| 956 | */ | 956 | */ |
| 957 | 957 | ||
| 958 | if (ssize <= IDATASIZE) { | 958 | if (ssize <= IDATASIZE) { |
| 959 | ip->i_op = &jfs_symlink_inode_operations; | 959 | ip->i_op = &jfs_fast_symlink_inode_operations; |
| 960 | 960 | ||
| 961 | i_fastsymlink = JFS_IP(ip)->i_inline; | 961 | i_fastsymlink = JFS_IP(ip)->i_inline; |
| 962 | memcpy(i_fastsymlink, name, ssize); | 962 | memcpy(i_fastsymlink, name, ssize); |
| @@ -978,7 +978,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
| 978 | else { | 978 | else { |
| 979 | jfs_info("jfs_symlink: allocate extent ip:0x%p", ip); | 979 | jfs_info("jfs_symlink: allocate extent ip:0x%p", ip); |
| 980 | 980 | ||
| 981 | ip->i_op = &page_symlink_inode_operations; | 981 | ip->i_op = &jfs_symlink_inode_operations; |
| 982 | ip->i_mapping->a_ops = &jfs_aops; | 982 | ip->i_mapping->a_ops = &jfs_aops; |
| 983 | 983 | ||
| 984 | /* | 984 | /* |
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index 7f24a0bb08ca..1aba0039f1c9 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c | |||
| @@ -81,6 +81,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) | |||
| 81 | struct inode *iplist[1]; | 81 | struct inode *iplist[1]; |
| 82 | struct jfs_superblock *j_sb, *j_sb2; | 82 | struct jfs_superblock *j_sb, *j_sb2; |
| 83 | uint old_agsize; | 83 | uint old_agsize; |
| 84 | int agsizechanged = 0; | ||
| 84 | struct buffer_head *bh, *bh2; | 85 | struct buffer_head *bh, *bh2; |
| 85 | 86 | ||
| 86 | /* If the volume hasn't grown, get out now */ | 87 | /* If the volume hasn't grown, get out now */ |
| @@ -333,6 +334,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) | |||
| 333 | */ | 334 | */ |
| 334 | if ((rc = dbExtendFS(ipbmap, XAddress, nblocks))) | 335 | if ((rc = dbExtendFS(ipbmap, XAddress, nblocks))) |
| 335 | goto error_out; | 336 | goto error_out; |
| 337 | |||
| 338 | agsizechanged |= (bmp->db_agsize != old_agsize); | ||
| 339 | |||
| 336 | /* | 340 | /* |
| 337 | * the map now has extended to cover additional nblocks: | 341 | * the map now has extended to cover additional nblocks: |
| 338 | * dn_mapsize = oldMapsize + nblocks; | 342 | * dn_mapsize = oldMapsize + nblocks; |
| @@ -432,7 +436,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) | |||
| 432 | * will correctly identify the new ag); | 436 | * will correctly identify the new ag); |
| 433 | */ | 437 | */ |
| 434 | /* if new AG size the same as old AG size, done! */ | 438 | /* if new AG size the same as old AG size, done! */ |
| 435 | if (bmp->db_agsize != old_agsize) { | 439 | if (agsizechanged) { |
| 436 | if ((rc = diExtendFS(ipimap, ipbmap))) | 440 | if ((rc = diExtendFS(ipimap, ipbmap))) |
| 437 | goto error_out; | 441 | goto error_out; |
| 438 | 442 | ||
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c index 4af1a05aad0a..205b946d8e0d 100644 --- a/fs/jfs/symlink.c +++ b/fs/jfs/symlink.c | |||
| @@ -29,9 +29,21 @@ static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 29 | return NULL; | 29 | return NULL; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | const struct inode_operations jfs_symlink_inode_operations = { | 32 | const struct inode_operations jfs_fast_symlink_inode_operations = { |
| 33 | .readlink = generic_readlink, | 33 | .readlink = generic_readlink, |
| 34 | .follow_link = jfs_follow_link, | 34 | .follow_link = jfs_follow_link, |
| 35 | .setattr = jfs_setattr, | ||
| 36 | .setxattr = jfs_setxattr, | ||
| 37 | .getxattr = jfs_getxattr, | ||
| 38 | .listxattr = jfs_listxattr, | ||
| 39 | .removexattr = jfs_removexattr, | ||
| 40 | }; | ||
| 41 | |||
| 42 | const struct inode_operations jfs_symlink_inode_operations = { | ||
| 43 | .readlink = generic_readlink, | ||
| 44 | .follow_link = page_follow_link_light, | ||
| 45 | .put_link = page_put_link, | ||
| 46 | .setattr = jfs_setattr, | ||
| 35 | .setxattr = jfs_setxattr, | 47 | .setxattr = jfs_setxattr, |
| 36 | .getxattr = jfs_getxattr, | 48 | .getxattr = jfs_getxattr, |
| 37 | .listxattr = jfs_listxattr, | 49 | .listxattr = jfs_listxattr, |
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c index 84e36f52fe95..76c242fbe1b0 100644 --- a/fs/logfs/gc.c +++ b/fs/logfs/gc.c | |||
| @@ -459,6 +459,14 @@ static void __logfs_gc_pass(struct super_block *sb, int target) | |||
| 459 | struct logfs_block *block; | 459 | struct logfs_block *block; |
| 460 | int round, progress, last_progress = 0; | 460 | int round, progress, last_progress = 0; |
| 461 | 461 | ||
| 462 | /* | ||
| 463 | * Doing too many changes to the segfile at once would result | ||
| 464 | * in a large number of aliases. Write the journal before | ||
| 465 | * things get out of hand. | ||
| 466 | */ | ||
| 467 | if (super->s_shadow_tree.no_shadowed_segments >= MAX_OBJ_ALIASES) | ||
| 468 | logfs_write_anchor(sb); | ||
| 469 | |||
| 462 | if (no_free_segments(sb) >= target && | 470 | if (no_free_segments(sb) >= target && |
| 463 | super->s_no_object_aliases < MAX_OBJ_ALIASES) | 471 | super->s_no_object_aliases < MAX_OBJ_ALIASES) |
| 464 | return; | 472 | return; |
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c index 33bd260b8309..fb0a613f885b 100644 --- a/fs/logfs/journal.c +++ b/fs/logfs/journal.c | |||
| @@ -389,7 +389,10 @@ static void journal_get_erase_count(struct logfs_area *area) | |||
| 389 | static int journal_erase_segment(struct logfs_area *area) | 389 | static int journal_erase_segment(struct logfs_area *area) |
| 390 | { | 390 | { |
| 391 | struct super_block *sb = area->a_sb; | 391 | struct super_block *sb = area->a_sb; |
| 392 | struct logfs_segment_header sh; | 392 | union { |
| 393 | struct logfs_segment_header sh; | ||
| 394 | unsigned char c[ALIGN(sizeof(struct logfs_segment_header), 16)]; | ||
| 395 | } u; | ||
| 393 | u64 ofs; | 396 | u64 ofs; |
| 394 | int err; | 397 | int err; |
| 395 | 398 | ||
| @@ -397,20 +400,21 @@ static int journal_erase_segment(struct logfs_area *area) | |||
| 397 | if (err) | 400 | if (err) |
| 398 | return err; | 401 | return err; |
| 399 | 402 | ||
| 400 | sh.pad = 0; | 403 | memset(&u, 0, sizeof(u)); |
| 401 | sh.type = SEG_JOURNAL; | 404 | u.sh.pad = 0; |
| 402 | sh.level = 0; | 405 | u.sh.type = SEG_JOURNAL; |
| 403 | sh.segno = cpu_to_be32(area->a_segno); | 406 | u.sh.level = 0; |
| 404 | sh.ec = cpu_to_be32(area->a_erase_count); | 407 | u.sh.segno = cpu_to_be32(area->a_segno); |
| 405 | sh.gec = cpu_to_be64(logfs_super(sb)->s_gec); | 408 | u.sh.ec = cpu_to_be32(area->a_erase_count); |
| 406 | sh.crc = logfs_crc32(&sh, sizeof(sh), 4); | 409 | u.sh.gec = cpu_to_be64(logfs_super(sb)->s_gec); |
| 410 | u.sh.crc = logfs_crc32(&u.sh, sizeof(u.sh), 4); | ||
| 407 | 411 | ||
| 408 | /* This causes a bug in segment.c. Not yet. */ | 412 | /* This causes a bug in segment.c. Not yet. */ |
| 409 | //logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count, 0); | 413 | //logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count, 0); |
| 410 | 414 | ||
| 411 | ofs = dev_ofs(sb, area->a_segno, 0); | 415 | ofs = dev_ofs(sb, area->a_segno, 0); |
| 412 | area->a_used_bytes = ALIGN(sizeof(sh), 16); | 416 | area->a_used_bytes = sizeof(u); |
| 413 | logfs_buf_write(area, ofs, &sh, sizeof(sh)); | 417 | logfs_buf_write(area, ofs, &u, sizeof(u)); |
| 414 | return 0; | 418 | return 0; |
| 415 | } | 419 | } |
| 416 | 420 | ||
| @@ -494,6 +498,8 @@ static void account_shadows(struct super_block *sb) | |||
| 494 | 498 | ||
| 495 | btree_grim_visitor64(&tree->new, (unsigned long)sb, account_shadow); | 499 | btree_grim_visitor64(&tree->new, (unsigned long)sb, account_shadow); |
| 496 | btree_grim_visitor64(&tree->old, (unsigned long)sb, account_shadow); | 500 | btree_grim_visitor64(&tree->old, (unsigned long)sb, account_shadow); |
| 501 | btree_grim_visitor32(&tree->segment_map, 0, NULL); | ||
| 502 | tree->no_shadowed_segments = 0; | ||
| 497 | 503 | ||
| 498 | if (li->li_block) { | 504 | if (li->li_block) { |
| 499 | /* | 505 | /* |
| @@ -607,9 +613,9 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type, | |||
| 607 | if (len == 0) | 613 | if (len == 0) |
| 608 | return logfs_write_header(super, header, 0, type); | 614 | return logfs_write_header(super, header, 0, type); |
| 609 | 615 | ||
| 616 | BUG_ON(len > sb->s_blocksize); | ||
| 610 | compr_len = logfs_compress(buf, data, len, sb->s_blocksize); | 617 | compr_len = logfs_compress(buf, data, len, sb->s_blocksize); |
| 611 | if (compr_len < 0 || type == JE_ANCHOR) { | 618 | if (compr_len < 0 || type == JE_ANCHOR) { |
| 612 | BUG_ON(len > sb->s_blocksize); | ||
| 613 | memcpy(data, buf, len); | 619 | memcpy(data, buf, len); |
| 614 | compr_len = len; | 620 | compr_len = len; |
| 615 | compr = COMPR_NONE; | 621 | compr = COMPR_NONE; |
| @@ -661,6 +667,7 @@ static int logfs_write_je_buf(struct super_block *sb, void *buf, u16 type, | |||
| 661 | if (ofs < 0) | 667 | if (ofs < 0) |
| 662 | return ofs; | 668 | return ofs; |
| 663 | logfs_buf_write(area, ofs, super->s_compressed_je, len); | 669 | logfs_buf_write(area, ofs, super->s_compressed_je, len); |
| 670 | BUG_ON(super->s_no_je >= MAX_JOURNAL_ENTRIES); | ||
| 664 | super->s_je_array[super->s_no_je++] = cpu_to_be64(ofs); | 671 | super->s_je_array[super->s_no_je++] = cpu_to_be64(ofs); |
| 665 | return 0; | 672 | return 0; |
| 666 | } | 673 | } |
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index b84b0eec6024..0a3df1a0c936 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h | |||
| @@ -257,10 +257,14 @@ struct logfs_shadow { | |||
| 257 | * struct shadow_tree | 257 | * struct shadow_tree |
| 258 | * @new: shadows where old_ofs==0, indexed by new_ofs | 258 | * @new: shadows where old_ofs==0, indexed by new_ofs |
| 259 | * @old: shadows where old_ofs!=0, indexed by old_ofs | 259 | * @old: shadows where old_ofs!=0, indexed by old_ofs |
| 260 | * @segment_map: bitfield of segments containing shadows | ||
| 261 | * @no_shadowed_segment: number of segments containing shadows | ||
| 260 | */ | 262 | */ |
| 261 | struct shadow_tree { | 263 | struct shadow_tree { |
| 262 | struct btree_head64 new; | 264 | struct btree_head64 new; |
| 263 | struct btree_head64 old; | 265 | struct btree_head64 old; |
| 266 | struct btree_head32 segment_map; | ||
| 267 | int no_shadowed_segments; | ||
| 264 | }; | 268 | }; |
| 265 | 269 | ||
| 266 | struct object_alias_item { | 270 | struct object_alias_item { |
| @@ -305,13 +309,14 @@ typedef int write_alias_t(struct super_block *sb, u64 ino, u64 bix, | |||
| 305 | level_t level, int child_no, __be64 val); | 309 | level_t level, int child_no, __be64 val); |
| 306 | struct logfs_block_ops { | 310 | struct logfs_block_ops { |
| 307 | void (*write_block)(struct logfs_block *block); | 311 | void (*write_block)(struct logfs_block *block); |
| 308 | gc_level_t (*block_level)(struct logfs_block *block); | ||
| 309 | void (*free_block)(struct super_block *sb, struct logfs_block*block); | 312 | void (*free_block)(struct super_block *sb, struct logfs_block*block); |
| 310 | int (*write_alias)(struct super_block *sb, | 313 | int (*write_alias)(struct super_block *sb, |
| 311 | struct logfs_block *block, | 314 | struct logfs_block *block, |
| 312 | write_alias_t *write_one_alias); | 315 | write_alias_t *write_one_alias); |
| 313 | }; | 316 | }; |
| 314 | 317 | ||
| 318 | #define MAX_JOURNAL_ENTRIES 256 | ||
| 319 | |||
| 315 | struct logfs_super { | 320 | struct logfs_super { |
| 316 | struct mtd_info *s_mtd; /* underlying device */ | 321 | struct mtd_info *s_mtd; /* underlying device */ |
| 317 | struct block_device *s_bdev; /* underlying device */ | 322 | struct block_device *s_bdev; /* underlying device */ |
| @@ -378,7 +383,7 @@ struct logfs_super { | |||
| 378 | u32 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */ | 383 | u32 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */ |
| 379 | u64 s_last_version; | 384 | u64 s_last_version; |
| 380 | struct logfs_area *s_journal_area; /* open journal segment */ | 385 | struct logfs_area *s_journal_area; /* open journal segment */ |
| 381 | __be64 s_je_array[64]; | 386 | __be64 s_je_array[MAX_JOURNAL_ENTRIES]; |
| 382 | int s_no_je; | 387 | int s_no_je; |
| 383 | 388 | ||
| 384 | int s_sum_index; /* for the 12 summaries */ | 389 | int s_sum_index; /* for the 12 summaries */ |
| @@ -722,4 +727,10 @@ static inline struct logfs_area *get_area(struct super_block *sb, | |||
| 722 | return logfs_super(sb)->s_area[(__force u8)gc_level]; | 727 | return logfs_super(sb)->s_area[(__force u8)gc_level]; |
| 723 | } | 728 | } |
| 724 | 729 | ||
| 730 | static inline void logfs_mempool_destroy(mempool_t *pool) | ||
| 731 | { | ||
| 732 | if (pool) | ||
| 733 | mempool_destroy(pool); | ||
| 734 | } | ||
| 735 | |||
| 725 | #endif | 736 | #endif |
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index bff40253dfb2..3159db6958e5 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c | |||
| @@ -430,25 +430,6 @@ static void inode_write_block(struct logfs_block *block) | |||
| 430 | } | 430 | } |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | static gc_level_t inode_block_level(struct logfs_block *block) | ||
| 434 | { | ||
| 435 | BUG_ON(block->inode->i_ino == LOGFS_INO_MASTER); | ||
| 436 | return GC_LEVEL(LOGFS_MAX_LEVELS); | ||
| 437 | } | ||
| 438 | |||
| 439 | static gc_level_t indirect_block_level(struct logfs_block *block) | ||
| 440 | { | ||
| 441 | struct page *page; | ||
| 442 | struct inode *inode; | ||
| 443 | u64 bix; | ||
| 444 | level_t level; | ||
| 445 | |||
| 446 | page = block->page; | ||
| 447 | inode = page->mapping->host; | ||
| 448 | logfs_unpack_index(page->index, &bix, &level); | ||
| 449 | return expand_level(inode->i_ino, level); | ||
| 450 | } | ||
| 451 | |||
| 452 | /* | 433 | /* |
| 453 | * This silences a false, yet annoying gcc warning. I hate it when my editor | 434 | * This silences a false, yet annoying gcc warning. I hate it when my editor |
| 454 | * jumps into bitops.h each time I recompile this file. | 435 | * jumps into bitops.h each time I recompile this file. |
| @@ -587,14 +568,12 @@ static void indirect_free_block(struct super_block *sb, | |||
| 587 | 568 | ||
| 588 | static struct logfs_block_ops inode_block_ops = { | 569 | static struct logfs_block_ops inode_block_ops = { |
| 589 | .write_block = inode_write_block, | 570 | .write_block = inode_write_block, |
| 590 | .block_level = inode_block_level, | ||
| 591 | .free_block = inode_free_block, | 571 | .free_block = inode_free_block, |
| 592 | .write_alias = inode_write_alias, | 572 | .write_alias = inode_write_alias, |
| 593 | }; | 573 | }; |
| 594 | 574 | ||
| 595 | struct logfs_block_ops indirect_block_ops = { | 575 | struct logfs_block_ops indirect_block_ops = { |
| 596 | .write_block = indirect_write_block, | 576 | .write_block = indirect_write_block, |
| 597 | .block_level = indirect_block_level, | ||
| 598 | .free_block = indirect_free_block, | 577 | .free_block = indirect_free_block, |
| 599 | .write_alias = indirect_write_alias, | 578 | .write_alias = indirect_write_alias, |
| 600 | }; | 579 | }; |
| @@ -1241,6 +1220,18 @@ static void free_shadow(struct inode *inode, struct logfs_shadow *shadow) | |||
| 1241 | mempool_free(shadow, super->s_shadow_pool); | 1220 | mempool_free(shadow, super->s_shadow_pool); |
| 1242 | } | 1221 | } |
| 1243 | 1222 | ||
| 1223 | static void mark_segment(struct shadow_tree *tree, u32 segno) | ||
| 1224 | { | ||
| 1225 | int err; | ||
| 1226 | |||
| 1227 | if (!btree_lookup32(&tree->segment_map, segno)) { | ||
| 1228 | err = btree_insert32(&tree->segment_map, segno, (void *)1, | ||
| 1229 | GFP_NOFS); | ||
| 1230 | BUG_ON(err); | ||
| 1231 | tree->no_shadowed_segments++; | ||
| 1232 | } | ||
| 1233 | } | ||
| 1234 | |||
| 1244 | /** | 1235 | /** |
| 1245 | * fill_shadow_tree - Propagate shadow tree changes due to a write | 1236 | * fill_shadow_tree - Propagate shadow tree changes due to a write |
| 1246 | * @inode: Inode owning the page | 1237 | * @inode: Inode owning the page |
| @@ -1288,6 +1279,8 @@ static void fill_shadow_tree(struct inode *inode, struct page *page, | |||
| 1288 | 1279 | ||
| 1289 | super->s_dirty_used_bytes += shadow->new_len; | 1280 | super->s_dirty_used_bytes += shadow->new_len; |
| 1290 | super->s_dirty_free_bytes += shadow->old_len; | 1281 | super->s_dirty_free_bytes += shadow->old_len; |
| 1282 | mark_segment(tree, shadow->old_ofs >> super->s_segshift); | ||
| 1283 | mark_segment(tree, shadow->new_ofs >> super->s_segshift); | ||
| 1291 | } | 1284 | } |
| 1292 | } | 1285 | } |
| 1293 | 1286 | ||
| @@ -1845,19 +1838,37 @@ static int __logfs_truncate(struct inode *inode, u64 size) | |||
| 1845 | return logfs_truncate_direct(inode, size); | 1838 | return logfs_truncate_direct(inode, size); |
| 1846 | } | 1839 | } |
| 1847 | 1840 | ||
| 1848 | int logfs_truncate(struct inode *inode, u64 size) | 1841 | /* |
| 1842 | * Truncate, by changing the segment file, can consume a fair amount | ||
| 1843 | * of resources. So back off from time to time and do some GC. | ||
| 1844 | * 8 or 2048 blocks should be well within safety limits even if | ||
| 1845 | * every single block resided in a different segment. | ||
| 1846 | */ | ||
| 1847 | #define TRUNCATE_STEP (8 * 1024 * 1024) | ||
| 1848 | int logfs_truncate(struct inode *inode, u64 target) | ||
| 1849 | { | 1849 | { |
| 1850 | struct super_block *sb = inode->i_sb; | 1850 | struct super_block *sb = inode->i_sb; |
| 1851 | int err; | 1851 | u64 size = i_size_read(inode); |
| 1852 | int err = 0; | ||
| 1852 | 1853 | ||
| 1853 | logfs_get_wblocks(sb, NULL, 1); | 1854 | size = ALIGN(size, TRUNCATE_STEP); |
| 1854 | err = __logfs_truncate(inode, size); | 1855 | while (size > target) { |
| 1855 | if (!err) | 1856 | if (size > TRUNCATE_STEP) |
| 1856 | err = __logfs_write_inode(inode, 0); | 1857 | size -= TRUNCATE_STEP; |
| 1857 | logfs_put_wblocks(sb, NULL, 1); | 1858 | else |
| 1859 | size = 0; | ||
| 1860 | if (size < target) | ||
| 1861 | size = target; | ||
| 1862 | |||
| 1863 | logfs_get_wblocks(sb, NULL, 1); | ||
| 1864 | err = __logfs_truncate(inode, target); | ||
| 1865 | if (!err) | ||
| 1866 | err = __logfs_write_inode(inode, 0); | ||
| 1867 | logfs_put_wblocks(sb, NULL, 1); | ||
| 1868 | } | ||
| 1858 | 1869 | ||
| 1859 | if (!err) | 1870 | if (!err) |
| 1860 | err = vmtruncate(inode, size); | 1871 | err = vmtruncate(inode, target); |
| 1861 | 1872 | ||
| 1862 | /* I don't trust error recovery yet. */ | 1873 | /* I don't trust error recovery yet. */ |
| 1863 | WARN_ON(err); | 1874 | WARN_ON(err); |
| @@ -2251,8 +2262,6 @@ void logfs_cleanup_rw(struct super_block *sb) | |||
| 2251 | struct logfs_super *super = logfs_super(sb); | 2262 | struct logfs_super *super = logfs_super(sb); |
| 2252 | 2263 | ||
| 2253 | destroy_meta_inode(super->s_segfile_inode); | 2264 | destroy_meta_inode(super->s_segfile_inode); |
| 2254 | if (super->s_block_pool) | 2265 | logfs_mempool_destroy(super->s_block_pool); |
| 2255 | mempool_destroy(super->s_block_pool); | 2266 | logfs_mempool_destroy(super->s_shadow_pool); |
| 2256 | if (super->s_shadow_pool) | ||
| 2257 | mempool_destroy(super->s_shadow_pool); | ||
| 2258 | } | 2267 | } |
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index 801a3a141625..f77ce2b470ba 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c | |||
| @@ -183,14 +183,8 @@ static int btree_write_alias(struct super_block *sb, struct logfs_block *block, | |||
| 183 | return 0; | 183 | return 0; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static gc_level_t btree_block_level(struct logfs_block *block) | ||
| 187 | { | ||
| 188 | return expand_level(block->ino, block->level); | ||
| 189 | } | ||
| 190 | |||
| 191 | static struct logfs_block_ops btree_block_ops = { | 186 | static struct logfs_block_ops btree_block_ops = { |
| 192 | .write_block = btree_write_block, | 187 | .write_block = btree_write_block, |
| 193 | .block_level = btree_block_level, | ||
| 194 | .free_block = __free_block, | 188 | .free_block = __free_block, |
| 195 | .write_alias = btree_write_alias, | 189 | .write_alias = btree_write_alias, |
| 196 | }; | 190 | }; |
| @@ -919,7 +913,7 @@ err: | |||
| 919 | for (i--; i >= 0; i--) | 913 | for (i--; i >= 0; i--) |
| 920 | free_area(super->s_area[i]); | 914 | free_area(super->s_area[i]); |
| 921 | free_area(super->s_journal_area); | 915 | free_area(super->s_journal_area); |
| 922 | mempool_destroy(super->s_alias_pool); | 916 | logfs_mempool_destroy(super->s_alias_pool); |
| 923 | return -ENOMEM; | 917 | return -ENOMEM; |
| 924 | } | 918 | } |
| 925 | 919 | ||
diff --git a/fs/logfs/super.c b/fs/logfs/super.c index b60bfac3263c..5866ee6e1327 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "logfs.h" | 12 | #include "logfs.h" |
| 13 | #include <linux/bio.h> | 13 | #include <linux/bio.h> |
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/blkdev.h> | ||
| 15 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
| 16 | #include <linux/statfs.h> | 17 | #include <linux/statfs.h> |
| 17 | #include <linux/buffer_head.h> | 18 | #include <linux/buffer_head.h> |
| @@ -137,6 +138,10 @@ static int logfs_sb_set(struct super_block *sb, void *_super) | |||
| 137 | sb->s_fs_info = super; | 138 | sb->s_fs_info = super; |
| 138 | sb->s_mtd = super->s_mtd; | 139 | sb->s_mtd = super->s_mtd; |
| 139 | sb->s_bdev = super->s_bdev; | 140 | sb->s_bdev = super->s_bdev; |
| 141 | if (sb->s_bdev) | ||
| 142 | sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info; | ||
| 143 | if (sb->s_mtd) | ||
| 144 | sb->s_bdi = sb->s_mtd->backing_dev_info; | ||
| 140 | return 0; | 145 | return 0; |
| 141 | } | 146 | } |
| 142 | 147 | ||
| @@ -452,6 +457,8 @@ static int logfs_read_sb(struct super_block *sb, int read_only) | |||
| 452 | 457 | ||
| 453 | btree_init_mempool64(&super->s_shadow_tree.new, super->s_btree_pool); | 458 | btree_init_mempool64(&super->s_shadow_tree.new, super->s_btree_pool); |
| 454 | btree_init_mempool64(&super->s_shadow_tree.old, super->s_btree_pool); | 459 | btree_init_mempool64(&super->s_shadow_tree.old, super->s_btree_pool); |
| 460 | btree_init_mempool32(&super->s_shadow_tree.segment_map, | ||
| 461 | super->s_btree_pool); | ||
| 455 | 462 | ||
| 456 | ret = logfs_init_mapping(sb); | 463 | ret = logfs_init_mapping(sb); |
| 457 | if (ret) | 464 | if (ret) |
| @@ -516,8 +523,8 @@ static void logfs_kill_sb(struct super_block *sb) | |||
| 516 | if (super->s_erase_page) | 523 | if (super->s_erase_page) |
| 517 | __free_page(super->s_erase_page); | 524 | __free_page(super->s_erase_page); |
| 518 | super->s_devops->put_device(sb); | 525 | super->s_devops->put_device(sb); |
| 519 | mempool_destroy(super->s_btree_pool); | 526 | logfs_mempool_destroy(super->s_btree_pool); |
| 520 | mempool_destroy(super->s_alias_pool); | 527 | logfs_mempool_destroy(super->s_alias_pool); |
| 521 | kfree(super); | 528 | kfree(super); |
| 522 | log_super("LogFS: Finished unmounting\n"); | 529 | log_super("LogFS: Finished unmounting\n"); |
| 523 | } | 530 | } |
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/dir.c b/fs/nfs/dir.c index be46f26c9a56..db3ad849a289 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); |
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/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..dc72491a19f9 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -693,6 +693,7 @@ int set_anon_super(struct super_block *s, void *data) | |||
| 693 | return -EMFILE; | 693 | return -EMFILE; |
| 694 | } | 694 | } |
| 695 | s->s_dev = MKDEV(0, dev & MINORMASK); | 695 | s->s_dev = MKDEV(0, dev & MINORMASK); |
| 696 | s->s_bdi = &noop_backing_dev_info; | ||
| 696 | return 0; | 697 | return 0; |
| 697 | } | 698 | } |
| 698 | 699 | ||
| @@ -954,10 +955,11 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
| 954 | if (error < 0) | 955 | if (error < 0) |
| 955 | goto out_free_secdata; | 956 | goto out_free_secdata; |
| 956 | BUG_ON(!mnt->mnt_sb); | 957 | BUG_ON(!mnt->mnt_sb); |
| 958 | WARN_ON(!mnt->mnt_sb->s_bdi); | ||
| 957 | 959 | ||
| 958 | error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); | 960 | error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); |
| 959 | if (error) | 961 | if (error) |
| 960 | goto out_sb; | 962 | goto out_sb; |
| 961 | 963 | ||
| 962 | /* | 964 | /* |
| 963 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE | 965 | * 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/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; |
