diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/affs/affs.h | 4 | ||||
| -rw-r--r-- | fs/affs/file.c | 25 | ||||
| -rw-r--r-- | fs/affs/inode.c | 34 | ||||
| -rw-r--r-- | fs/affs/namei.c | 6 | ||||
| -rw-r--r-- | fs/affs/super.c | 18 | ||||
| -rw-r--r-- | fs/bio.c | 3 | ||||
| -rw-r--r-- | fs/inode.c | 5 | ||||
| -rw-r--r-- | fs/locks.c | 17 | ||||
| -rw-r--r-- | fs/pipe.c | 6 | ||||
| -rw-r--r-- | fs/proc/task_mmu.c | 2 | ||||
| -rw-r--r-- | fs/splice.c | 31 | ||||
| -rw-r--r-- | fs/udf/namei.c | 145 | ||||
| -rw-r--r-- | fs/udf/partition.c | 4 | ||||
| -rw-r--r-- | fs/udf/super.c | 1 | ||||
| -rw-r--r-- | fs/udf/udfdecl.h | 1 |
15 files changed, 222 insertions, 80 deletions
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index d5bd497ab9cb..223b1917093e 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
| @@ -48,7 +48,7 @@ struct affs_ext_key { | |||
| 48 | * affs fs inode data in memory | 48 | * affs fs inode data in memory |
| 49 | */ | 49 | */ |
| 50 | struct affs_inode_info { | 50 | struct affs_inode_info { |
| 51 | u32 i_opencnt; | 51 | atomic_t i_opencnt; |
| 52 | struct semaphore i_link_lock; /* Protects internal inode access. */ | 52 | struct semaphore i_link_lock; /* Protects internal inode access. */ |
| 53 | struct semaphore i_ext_lock; /* Protects internal inode access. */ | 53 | struct semaphore i_ext_lock; /* Protects internal inode access. */ |
| 54 | #define i_hash_lock i_ext_lock | 54 | #define i_hash_lock i_ext_lock |
| @@ -170,8 +170,6 @@ extern int affs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 170 | extern unsigned long affs_parent_ino(struct inode *dir); | 170 | extern unsigned long affs_parent_ino(struct inode *dir); |
| 171 | extern struct inode *affs_new_inode(struct inode *dir); | 171 | extern struct inode *affs_new_inode(struct inode *dir); |
| 172 | extern int affs_notify_change(struct dentry *dentry, struct iattr *attr); | 172 | extern int affs_notify_change(struct dentry *dentry, struct iattr *attr); |
| 173 | extern void affs_put_inode(struct inode *inode); | ||
| 174 | extern void affs_drop_inode(struct inode *inode); | ||
| 175 | extern void affs_delete_inode(struct inode *inode); | 173 | extern void affs_delete_inode(struct inode *inode); |
| 176 | extern void affs_clear_inode(struct inode *inode); | 174 | extern void affs_clear_inode(struct inode *inode); |
| 177 | extern struct inode *affs_iget(struct super_block *sb, | 175 | extern struct inode *affs_iget(struct super_block *sb, |
diff --git a/fs/affs/file.c b/fs/affs/file.c index 1a4f092f24ef..6eac7bdeec94 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
| @@ -48,8 +48,9 @@ affs_file_open(struct inode *inode, struct file *filp) | |||
| 48 | { | 48 | { |
| 49 | if (atomic_read(&filp->f_count) != 1) | 49 | if (atomic_read(&filp->f_count) != 1) |
| 50 | return 0; | 50 | return 0; |
| 51 | pr_debug("AFFS: open(%d)\n", AFFS_I(inode)->i_opencnt); | 51 | pr_debug("AFFS: open(%lu,%d)\n", |
| 52 | AFFS_I(inode)->i_opencnt++; | 52 | inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt)); |
| 53 | atomic_inc(&AFFS_I(inode)->i_opencnt); | ||
| 53 | return 0; | 54 | return 0; |
| 54 | } | 55 | } |
| 55 | 56 | ||
| @@ -58,10 +59,16 @@ affs_file_release(struct inode *inode, struct file *filp) | |||
| 58 | { | 59 | { |
| 59 | if (atomic_read(&filp->f_count) != 0) | 60 | if (atomic_read(&filp->f_count) != 0) |
| 60 | return 0; | 61 | return 0; |
| 61 | pr_debug("AFFS: release(%d)\n", AFFS_I(inode)->i_opencnt); | 62 | pr_debug("AFFS: release(%lu, %d)\n", |
| 62 | AFFS_I(inode)->i_opencnt--; | 63 | inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt)); |
| 63 | if (!AFFS_I(inode)->i_opencnt) | 64 | |
| 65 | if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) { | ||
| 66 | mutex_lock(&inode->i_mutex); | ||
| 67 | if (inode->i_size != AFFS_I(inode)->mmu_private) | ||
| 68 | affs_truncate(inode); | ||
| 64 | affs_free_prealloc(inode); | 69 | affs_free_prealloc(inode); |
| 70 | mutex_unlock(&inode->i_mutex); | ||
| 71 | } | ||
| 65 | 72 | ||
| 66 | return 0; | 73 | return 0; |
| 67 | } | 74 | } |
| @@ -180,7 +187,7 @@ affs_get_extblock(struct inode *inode, u32 ext) | |||
| 180 | /* inline the simplest case: same extended block as last time */ | 187 | /* inline the simplest case: same extended block as last time */ |
| 181 | struct buffer_head *bh = AFFS_I(inode)->i_ext_bh; | 188 | struct buffer_head *bh = AFFS_I(inode)->i_ext_bh; |
| 182 | if (ext == AFFS_I(inode)->i_ext_last) | 189 | if (ext == AFFS_I(inode)->i_ext_last) |
| 183 | atomic_inc(&bh->b_count); | 190 | get_bh(bh); |
| 184 | else | 191 | else |
| 185 | /* we have to do more (not inlined) */ | 192 | /* we have to do more (not inlined) */ |
| 186 | bh = affs_get_extblock_slow(inode, ext); | 193 | bh = affs_get_extblock_slow(inode, ext); |
| @@ -306,7 +313,7 @@ store_ext: | |||
| 306 | affs_brelse(AFFS_I(inode)->i_ext_bh); | 313 | affs_brelse(AFFS_I(inode)->i_ext_bh); |
| 307 | AFFS_I(inode)->i_ext_last = ext; | 314 | AFFS_I(inode)->i_ext_last = ext; |
| 308 | AFFS_I(inode)->i_ext_bh = bh; | 315 | AFFS_I(inode)->i_ext_bh = bh; |
| 309 | atomic_inc(&bh->b_count); | 316 | get_bh(bh); |
| 310 | 317 | ||
| 311 | return bh; | 318 | return bh; |
| 312 | 319 | ||
| @@ -324,7 +331,6 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul | |||
| 324 | 331 | ||
| 325 | pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block); | 332 | pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block); |
| 326 | 333 | ||
| 327 | |||
| 328 | BUG_ON(block > (sector_t)0x7fffffffUL); | 334 | BUG_ON(block > (sector_t)0x7fffffffUL); |
| 329 | 335 | ||
| 330 | if (block >= AFFS_I(inode)->i_blkcnt) { | 336 | if (block >= AFFS_I(inode)->i_blkcnt) { |
| @@ -827,6 +833,8 @@ affs_truncate(struct inode *inode) | |||
| 827 | res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata); | 833 | res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata); |
| 828 | if (!res) | 834 | if (!res) |
| 829 | res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata); | 835 | res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata); |
| 836 | else | ||
| 837 | inode->i_size = AFFS_I(inode)->mmu_private; | ||
| 830 | mark_inode_dirty(inode); | 838 | mark_inode_dirty(inode); |
| 831 | return; | 839 | return; |
| 832 | } else if (inode->i_size == AFFS_I(inode)->mmu_private) | 840 | } else if (inode->i_size == AFFS_I(inode)->mmu_private) |
| @@ -862,6 +870,7 @@ affs_truncate(struct inode *inode) | |||
| 862 | blk++; | 870 | blk++; |
| 863 | } else | 871 | } else |
| 864 | AFFS_HEAD(ext_bh)->first_data = 0; | 872 | AFFS_HEAD(ext_bh)->first_data = 0; |
| 873 | AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(i); | ||
| 865 | size = AFFS_SB(sb)->s_hashsize; | 874 | size = AFFS_SB(sb)->s_hashsize; |
| 866 | if (size > blkcnt - blk + i) | 875 | if (size > blkcnt - blk + i) |
| 867 | size = blkcnt - blk + i; | 876 | size = blkcnt - blk + i; |
diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 27fe6cbe43ae..a13b334a3910 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c | |||
| @@ -58,7 +58,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) | |||
| 58 | AFFS_I(inode)->i_extcnt = 1; | 58 | AFFS_I(inode)->i_extcnt = 1; |
| 59 | AFFS_I(inode)->i_ext_last = ~1; | 59 | AFFS_I(inode)->i_ext_last = ~1; |
| 60 | AFFS_I(inode)->i_protect = prot; | 60 | AFFS_I(inode)->i_protect = prot; |
| 61 | AFFS_I(inode)->i_opencnt = 0; | 61 | atomic_set(&AFFS_I(inode)->i_opencnt, 0); |
| 62 | AFFS_I(inode)->i_blkcnt = 0; | 62 | AFFS_I(inode)->i_blkcnt = 0; |
| 63 | AFFS_I(inode)->i_lc = NULL; | 63 | AFFS_I(inode)->i_lc = NULL; |
| 64 | AFFS_I(inode)->i_lc_size = 0; | 64 | AFFS_I(inode)->i_lc_size = 0; |
| @@ -108,8 +108,6 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) | |||
| 108 | inode->i_mode |= S_IFDIR; | 108 | inode->i_mode |= S_IFDIR; |
| 109 | } else | 109 | } else |
| 110 | inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR; | 110 | inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR; |
| 111 | if (tail->link_chain) | ||
| 112 | inode->i_nlink = 2; | ||
| 113 | /* Maybe it should be controlled by mount parameter? */ | 111 | /* Maybe it should be controlled by mount parameter? */ |
| 114 | //inode->i_mode |= S_ISVTX; | 112 | //inode->i_mode |= S_ISVTX; |
| 115 | inode->i_op = &affs_dir_inode_operations; | 113 | inode->i_op = &affs_dir_inode_operations; |
| @@ -245,31 +243,12 @@ out: | |||
| 245 | } | 243 | } |
| 246 | 244 | ||
| 247 | void | 245 | void |
| 248 | affs_put_inode(struct inode *inode) | ||
| 249 | { | ||
| 250 | pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); | ||
| 251 | affs_free_prealloc(inode); | ||
| 252 | } | ||
| 253 | |||
| 254 | void | ||
| 255 | affs_drop_inode(struct inode *inode) | ||
| 256 | { | ||
| 257 | mutex_lock(&inode->i_mutex); | ||
| 258 | if (inode->i_size != AFFS_I(inode)->mmu_private) | ||
| 259 | affs_truncate(inode); | ||
| 260 | mutex_unlock(&inode->i_mutex); | ||
| 261 | |||
| 262 | generic_drop_inode(inode); | ||
| 263 | } | ||
| 264 | |||
| 265 | void | ||
| 266 | affs_delete_inode(struct inode *inode) | 246 | affs_delete_inode(struct inode *inode) |
| 267 | { | 247 | { |
| 268 | pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); | 248 | pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); |
| 269 | truncate_inode_pages(&inode->i_data, 0); | 249 | truncate_inode_pages(&inode->i_data, 0); |
| 270 | inode->i_size = 0; | 250 | inode->i_size = 0; |
| 271 | if (S_ISREG(inode->i_mode)) | 251 | affs_truncate(inode); |
| 272 | affs_truncate(inode); | ||
| 273 | clear_inode(inode); | 252 | clear_inode(inode); |
| 274 | affs_free_block(inode->i_sb, inode->i_ino); | 253 | affs_free_block(inode->i_sb, inode->i_ino); |
| 275 | } | 254 | } |
| @@ -277,9 +256,12 @@ affs_delete_inode(struct inode *inode) | |||
| 277 | void | 256 | void |
| 278 | affs_clear_inode(struct inode *inode) | 257 | affs_clear_inode(struct inode *inode) |
| 279 | { | 258 | { |
| 280 | unsigned long cache_page = (unsigned long) AFFS_I(inode)->i_lc; | 259 | unsigned long cache_page; |
| 281 | 260 | ||
| 282 | pr_debug("AFFS: clear_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); | 261 | pr_debug("AFFS: clear_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); |
| 262 | |||
| 263 | affs_free_prealloc(inode); | ||
| 264 | cache_page = (unsigned long)AFFS_I(inode)->i_lc; | ||
| 283 | if (cache_page) { | 265 | if (cache_page) { |
| 284 | pr_debug("AFFS: freeing ext cache\n"); | 266 | pr_debug("AFFS: freeing ext cache\n"); |
| 285 | AFFS_I(inode)->i_lc = NULL; | 267 | AFFS_I(inode)->i_lc = NULL; |
| @@ -316,7 +298,7 @@ affs_new_inode(struct inode *dir) | |||
| 316 | inode->i_ino = block; | 298 | inode->i_ino = block; |
| 317 | inode->i_nlink = 1; | 299 | inode->i_nlink = 1; |
| 318 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 300 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; |
| 319 | AFFS_I(inode)->i_opencnt = 0; | 301 | atomic_set(&AFFS_I(inode)->i_opencnt, 0); |
| 320 | AFFS_I(inode)->i_blkcnt = 0; | 302 | AFFS_I(inode)->i_blkcnt = 0; |
| 321 | AFFS_I(inode)->i_lc = NULL; | 303 | AFFS_I(inode)->i_lc = NULL; |
| 322 | AFFS_I(inode)->i_lc_size = 0; | 304 | AFFS_I(inode)->i_lc_size = 0; |
| @@ -369,12 +351,12 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3 | |||
| 369 | switch (type) { | 351 | switch (type) { |
| 370 | case ST_LINKFILE: | 352 | case ST_LINKFILE: |
| 371 | case ST_LINKDIR: | 353 | case ST_LINKDIR: |
| 372 | inode_bh = bh; | ||
| 373 | retval = -ENOSPC; | 354 | retval = -ENOSPC; |
| 374 | block = affs_alloc_block(dir, dir->i_ino); | 355 | block = affs_alloc_block(dir, dir->i_ino); |
| 375 | if (!block) | 356 | if (!block) |
| 376 | goto err; | 357 | goto err; |
| 377 | retval = -EIO; | 358 | retval = -EIO; |
| 359 | inode_bh = bh; | ||
| 378 | bh = affs_getzeroblk(sb, block); | 360 | bh = affs_getzeroblk(sb, block); |
| 379 | if (!bh) | 361 | if (!bh) |
| 380 | goto err; | 362 | goto err; |
diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 2218f1ee71ce..cfcf1b6cf82b 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c | |||
| @@ -234,7 +234,8 @@ affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
| 234 | int | 234 | int |
| 235 | affs_unlink(struct inode *dir, struct dentry *dentry) | 235 | affs_unlink(struct inode *dir, struct dentry *dentry) |
| 236 | { | 236 | { |
| 237 | pr_debug("AFFS: unlink(dir=%d, \"%.*s\")\n", (u32)dir->i_ino, | 237 | pr_debug("AFFS: unlink(dir=%d, %lu \"%.*s\")\n", (u32)dir->i_ino, |
| 238 | dentry->d_inode->i_ino, | ||
| 238 | (int)dentry->d_name.len, dentry->d_name.name); | 239 | (int)dentry->d_name.len, dentry->d_name.name); |
| 239 | 240 | ||
| 240 | return affs_remove_header(dentry); | 241 | return affs_remove_header(dentry); |
| @@ -302,7 +303,8 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 302 | int | 303 | int |
| 303 | affs_rmdir(struct inode *dir, struct dentry *dentry) | 304 | affs_rmdir(struct inode *dir, struct dentry *dentry) |
| 304 | { | 305 | { |
| 305 | pr_debug("AFFS: rmdir(dir=%u, \"%.*s\")\n", (u32)dir->i_ino, | 306 | pr_debug("AFFS: rmdir(dir=%u, %lu \"%.*s\")\n", (u32)dir->i_ino, |
| 307 | dentry->d_inode->i_ino, | ||
| 306 | (int)dentry->d_name.len, dentry->d_name.name); | 308 | (int)dentry->d_name.len, dentry->d_name.name); |
| 307 | 309 | ||
| 308 | return affs_remove_header(dentry); | 310 | return affs_remove_header(dentry); |
diff --git a/fs/affs/super.c b/fs/affs/super.c index 01d25d532541..d214837d5e42 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
| @@ -71,12 +71,18 @@ static struct kmem_cache * affs_inode_cachep; | |||
| 71 | 71 | ||
| 72 | static struct inode *affs_alloc_inode(struct super_block *sb) | 72 | static struct inode *affs_alloc_inode(struct super_block *sb) |
| 73 | { | 73 | { |
| 74 | struct affs_inode_info *ei; | 74 | struct affs_inode_info *i; |
| 75 | ei = (struct affs_inode_info *)kmem_cache_alloc(affs_inode_cachep, GFP_KERNEL); | 75 | |
| 76 | if (!ei) | 76 | i = kmem_cache_alloc(affs_inode_cachep, GFP_KERNEL); |
| 77 | if (!i) | ||
| 77 | return NULL; | 78 | return NULL; |
| 78 | ei->vfs_inode.i_version = 1; | 79 | |
| 79 | return &ei->vfs_inode; | 80 | i->vfs_inode.i_version = 1; |
| 81 | i->i_lc = NULL; | ||
| 82 | i->i_ext_bh = NULL; | ||
| 83 | i->i_pa_cnt = 0; | ||
| 84 | |||
| 85 | return &i->vfs_inode; | ||
| 80 | } | 86 | } |
| 81 | 87 | ||
| 82 | static void affs_destroy_inode(struct inode *inode) | 88 | static void affs_destroy_inode(struct inode *inode) |
| @@ -114,8 +120,6 @@ static const struct super_operations affs_sops = { | |||
| 114 | .alloc_inode = affs_alloc_inode, | 120 | .alloc_inode = affs_alloc_inode, |
| 115 | .destroy_inode = affs_destroy_inode, | 121 | .destroy_inode = affs_destroy_inode, |
| 116 | .write_inode = affs_write_inode, | 122 | .write_inode = affs_write_inode, |
| 117 | .put_inode = affs_put_inode, | ||
| 118 | .drop_inode = affs_drop_inode, | ||
| 119 | .delete_inode = affs_delete_inode, | 123 | .delete_inode = affs_delete_inode, |
| 120 | .clear_inode = affs_clear_inode, | 124 | .clear_inode = affs_clear_inode, |
| 121 | .put_super = affs_put_super, | 125 | .put_super = affs_put_super, |
| @@ -158,7 +158,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) | |||
| 158 | 158 | ||
| 159 | bio_init(bio); | 159 | bio_init(bio); |
| 160 | if (likely(nr_iovecs)) { | 160 | if (likely(nr_iovecs)) { |
| 161 | unsigned long idx = 0; /* shut up gcc */ | 161 | unsigned long uninitialized_var(idx); |
| 162 | 162 | ||
| 163 | bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); | 163 | bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); |
| 164 | if (unlikely(!bvl)) { | 164 | if (unlikely(!bvl)) { |
| @@ -963,6 +963,7 @@ static void bio_copy_kern_endio(struct bio *bio, int err) | |||
| 963 | * @data: pointer to buffer to copy | 963 | * @data: pointer to buffer to copy |
| 964 | * @len: length in bytes | 964 | * @len: length in bytes |
| 965 | * @gfp_mask: allocation flags for bio and page allocation | 965 | * @gfp_mask: allocation flags for bio and page allocation |
| 966 | * @reading: data direction is READ | ||
| 966 | * | 967 | * |
| 967 | * copy the kernel address into a bio suitable for io to a block | 968 | * copy the kernel address into a bio suitable for io to a block |
| 968 | * device. Returns an error pointer in case of error. | 969 | * device. Returns an error pointer in case of error. |
diff --git a/fs/inode.c b/fs/inode.c index bf6478130424..c36d9480335c 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -1149,13 +1149,8 @@ static inline void iput_final(struct inode *inode) | |||
| 1149 | void iput(struct inode *inode) | 1149 | void iput(struct inode *inode) |
| 1150 | { | 1150 | { |
| 1151 | if (inode) { | 1151 | if (inode) { |
| 1152 | const struct super_operations *op = inode->i_sb->s_op; | ||
| 1153 | |||
| 1154 | BUG_ON(inode->i_state == I_CLEAR); | 1152 | BUG_ON(inode->i_state == I_CLEAR); |
| 1155 | 1153 | ||
| 1156 | if (op && op->put_inode) | ||
| 1157 | op->put_inode(inode); | ||
| 1158 | |||
| 1159 | if (atomic_dec_and_lock(&inode->i_count, &inode_lock)) | 1154 | if (atomic_dec_and_lock(&inode->i_count, &inode_lock)) |
| 1160 | iput_final(inode); | 1155 | iput_final(inode); |
| 1161 | } | 1156 | } |
diff --git a/fs/locks.c b/fs/locks.c index 663c069b59b3..0ac6b92cb0b6 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -1753,6 +1753,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, | |||
| 1753 | struct file_lock *file_lock = locks_alloc_lock(); | 1753 | struct file_lock *file_lock = locks_alloc_lock(); |
| 1754 | struct flock flock; | 1754 | struct flock flock; |
| 1755 | struct inode *inode; | 1755 | struct inode *inode; |
| 1756 | struct file *f; | ||
| 1756 | int error; | 1757 | int error; |
| 1757 | 1758 | ||
| 1758 | if (file_lock == NULL) | 1759 | if (file_lock == NULL) |
| @@ -1825,7 +1826,15 @@ again: | |||
| 1825 | * Attempt to detect a close/fcntl race and recover by | 1826 | * Attempt to detect a close/fcntl race and recover by |
| 1826 | * releasing the lock that was just acquired. | 1827 | * releasing the lock that was just acquired. |
| 1827 | */ | 1828 | */ |
| 1828 | if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) { | 1829 | /* |
| 1830 | * we need that spin_lock here - it prevents reordering between | ||
| 1831 | * update of inode->i_flock and check for it done in close(). | ||
| 1832 | * rcu_read_lock() wouldn't do. | ||
| 1833 | */ | ||
| 1834 | spin_lock(¤t->files->file_lock); | ||
| 1835 | f = fcheck(fd); | ||
| 1836 | spin_unlock(¤t->files->file_lock); | ||
| 1837 | if (!error && f != filp && flock.l_type != F_UNLCK) { | ||
| 1829 | flock.l_type = F_UNLCK; | 1838 | flock.l_type = F_UNLCK; |
| 1830 | goto again; | 1839 | goto again; |
| 1831 | } | 1840 | } |
| @@ -1881,6 +1890,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, | |||
| 1881 | struct file_lock *file_lock = locks_alloc_lock(); | 1890 | struct file_lock *file_lock = locks_alloc_lock(); |
| 1882 | struct flock64 flock; | 1891 | struct flock64 flock; |
| 1883 | struct inode *inode; | 1892 | struct inode *inode; |
| 1893 | struct file *f; | ||
| 1884 | int error; | 1894 | int error; |
| 1885 | 1895 | ||
| 1886 | if (file_lock == NULL) | 1896 | if (file_lock == NULL) |
| @@ -1953,7 +1963,10 @@ again: | |||
| 1953 | * Attempt to detect a close/fcntl race and recover by | 1963 | * Attempt to detect a close/fcntl race and recover by |
| 1954 | * releasing the lock that was just acquired. | 1964 | * releasing the lock that was just acquired. |
| 1955 | */ | 1965 | */ |
| 1956 | if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) { | 1966 | spin_lock(¤t->files->file_lock); |
| 1967 | f = fcheck(fd); | ||
| 1968 | spin_unlock(¤t->files->file_lock); | ||
| 1969 | if (!error && f != filp && flock.l_type != F_UNLCK) { | ||
| 1957 | flock.l_type = F_UNLCK; | 1970 | flock.l_type = F_UNLCK; |
| 1958 | goto again; | 1971 | goto again; |
| 1959 | } | 1972 | } |
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
| 18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| 19 | #include <linux/audit.h> | 19 | #include <linux/audit.h> |
| 20 | #include <linux/syscalls.h> | ||
| 20 | 21 | ||
| 21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 22 | #include <asm/ioctls.h> | 23 | #include <asm/ioctls.h> |
| @@ -1086,8 +1087,11 @@ asmlinkage long __weak sys_pipe(int __user *fildes) | |||
| 1086 | 1087 | ||
| 1087 | error = do_pipe(fd); | 1088 | error = do_pipe(fd); |
| 1088 | if (!error) { | 1089 | if (!error) { |
| 1089 | if (copy_to_user(fildes, fd, sizeof(fd))) | 1090 | if (copy_to_user(fildes, fd, sizeof(fd))) { |
| 1091 | sys_close(fd[0]); | ||
| 1092 | sys_close(fd[1]); | ||
| 1090 | error = -EFAULT; | 1093 | error = -EFAULT; |
| 1094 | } | ||
| 1091 | } | 1095 | } |
| 1092 | return error; | 1096 | return error; |
| 1093 | } | 1097 | } |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index e2b8e769f510..88717c0f941b 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -5,11 +5,9 @@ | |||
| 5 | #include <linux/highmem.h> | 5 | #include <linux/highmem.h> |
| 6 | #include <linux/ptrace.h> | 6 | #include <linux/ptrace.h> |
| 7 | #include <linux/pagemap.h> | 7 | #include <linux/pagemap.h> |
| 8 | #include <linux/ptrace.h> | ||
| 9 | #include <linux/mempolicy.h> | 8 | #include <linux/mempolicy.h> |
| 10 | #include <linux/swap.h> | 9 | #include <linux/swap.h> |
| 11 | #include <linux/swapops.h> | 10 | #include <linux/swapops.h> |
| 12 | #include <linux/seq_file.h> | ||
| 13 | 11 | ||
| 14 | #include <asm/elf.h> | 12 | #include <asm/elf.h> |
| 15 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
diff --git a/fs/splice.c b/fs/splice.c index 633f58ebfb72..78150038b584 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -811,24 +811,19 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
| 811 | { | 811 | { |
| 812 | struct address_space *mapping = out->f_mapping; | 812 | struct address_space *mapping = out->f_mapping; |
| 813 | struct inode *inode = mapping->host; | 813 | struct inode *inode = mapping->host; |
| 814 | int killsuid, killpriv; | 814 | struct splice_desc sd = { |
| 815 | .total_len = len, | ||
| 816 | .flags = flags, | ||
| 817 | .pos = *ppos, | ||
| 818 | .u.file = out, | ||
| 819 | }; | ||
| 815 | ssize_t ret; | 820 | ssize_t ret; |
| 816 | int err = 0; | ||
| 817 | |||
| 818 | killpriv = security_inode_need_killpriv(out->f_path.dentry); | ||
| 819 | killsuid = should_remove_suid(out->f_path.dentry); | ||
| 820 | if (unlikely(killsuid || killpriv)) { | ||
| 821 | mutex_lock(&inode->i_mutex); | ||
| 822 | if (killpriv) | ||
| 823 | err = security_inode_killpriv(out->f_path.dentry); | ||
| 824 | if (!err && killsuid) | ||
| 825 | err = __remove_suid(out->f_path.dentry, killsuid); | ||
| 826 | mutex_unlock(&inode->i_mutex); | ||
| 827 | if (err) | ||
| 828 | return err; | ||
| 829 | } | ||
| 830 | 821 | ||
| 831 | ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 822 | inode_double_lock(inode, pipe->inode); |
| 823 | ret = remove_suid(out->f_path.dentry); | ||
| 824 | if (likely(!ret)) | ||
| 825 | ret = __splice_from_pipe(pipe, &sd, pipe_to_file); | ||
| 826 | inode_double_unlock(inode, pipe->inode); | ||
| 832 | if (ret > 0) { | 827 | if (ret > 0) { |
| 833 | unsigned long nr_pages; | 828 | unsigned long nr_pages; |
| 834 | 829 | ||
| @@ -840,6 +835,8 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
| 840 | * sync it. | 835 | * sync it. |
| 841 | */ | 836 | */ |
| 842 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | 837 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { |
| 838 | int err; | ||
| 839 | |||
| 843 | mutex_lock(&inode->i_mutex); | 840 | mutex_lock(&inode->i_mutex); |
| 844 | err = generic_osync_inode(inode, mapping, | 841 | err = generic_osync_inode(inode, mapping, |
| 845 | OSYNC_METADATA|OSYNC_DATA); | 842 | OSYNC_METADATA|OSYNC_DATA); |
| @@ -1075,7 +1072,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
| 1075 | 1072 | ||
| 1076 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); | 1073 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); |
| 1077 | if (ret > 0) | 1074 | if (ret > 0) |
| 1078 | *ppos = sd.pos; | 1075 | *ppos += ret; |
| 1079 | 1076 | ||
| 1080 | return ret; | 1077 | return ret; |
| 1081 | } | 1078 | } |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 2b34c8ca6c83..d3231947db19 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/buffer_head.h> | 32 | #include <linux/buffer_head.h> |
| 33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
| 34 | #include <linux/crc-itu-t.h> | 34 | #include <linux/crc-itu-t.h> |
| 35 | #include <linux/exportfs.h> | ||
| 35 | 36 | ||
| 36 | static inline int udf_match(int len1, const char *name1, int len2, | 37 | static inline int udf_match(int len1, const char *name1, int len2, |
| 37 | const char *name2) | 38 | const char *name2) |
| @@ -158,6 +159,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
| 158 | sector_t offset; | 159 | sector_t offset; |
| 159 | struct extent_position epos = {}; | 160 | struct extent_position epos = {}; |
| 160 | struct udf_inode_info *dinfo = UDF_I(dir); | 161 | struct udf_inode_info *dinfo = UDF_I(dir); |
| 162 | int isdotdot = dentry->d_name.len == 2 && | ||
| 163 | dentry->d_name.name[0] == '.' && dentry->d_name.name[1] == '.'; | ||
| 161 | 164 | ||
| 162 | size = udf_ext0_offset(dir) + dir->i_size; | 165 | size = udf_ext0_offset(dir) + dir->i_size; |
| 163 | f_pos = udf_ext0_offset(dir); | 166 | f_pos = udf_ext0_offset(dir); |
| @@ -225,6 +228,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
| 225 | continue; | 228 | continue; |
| 226 | } | 229 | } |
| 227 | 230 | ||
| 231 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) && | ||
| 232 | isdotdot) { | ||
| 233 | brelse(epos.bh); | ||
| 234 | return fi; | ||
| 235 | } | ||
| 236 | |||
| 228 | if (!lfi) | 237 | if (!lfi) |
| 229 | continue; | 238 | continue; |
| 230 | 239 | ||
| @@ -286,9 +295,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, | |||
| 286 | } | 295 | } |
| 287 | } | 296 | } |
| 288 | unlock_kernel(); | 297 | unlock_kernel(); |
| 289 | d_add(dentry, inode); | ||
| 290 | 298 | ||
| 291 | return NULL; | 299 | return d_splice_alias(inode, dentry); |
| 292 | } | 300 | } |
| 293 | 301 | ||
| 294 | static struct fileIdentDesc *udf_add_entry(struct inode *dir, | 302 | static struct fileIdentDesc *udf_add_entry(struct inode *dir, |
| @@ -307,7 +315,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
| 307 | uint16_t liu; | 315 | uint16_t liu; |
| 308 | int block; | 316 | int block; |
| 309 | kernel_lb_addr eloc; | 317 | kernel_lb_addr eloc; |
| 310 | uint32_t elen; | 318 | uint32_t elen = 0; |
| 311 | sector_t offset; | 319 | sector_t offset; |
| 312 | struct extent_position epos = {}; | 320 | struct extent_position epos = {}; |
| 313 | struct udf_inode_info *dinfo; | 321 | struct udf_inode_info *dinfo; |
| @@ -398,7 +406,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
| 398 | } | 406 | } |
| 399 | 407 | ||
| 400 | add: | 408 | add: |
| 401 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | 409 | /* Is there any extent whose size we need to round up? */ |
| 410 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) { | ||
| 402 | elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); | 411 | elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); |
| 403 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 412 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
| 404 | epos.offset -= sizeof(short_ad); | 413 | epos.offset -= sizeof(short_ad); |
| @@ -1232,6 +1241,134 @@ end_rename: | |||
| 1232 | return retval; | 1241 | return retval; |
| 1233 | } | 1242 | } |
| 1234 | 1243 | ||
| 1244 | static struct dentry *udf_get_parent(struct dentry *child) | ||
| 1245 | { | ||
| 1246 | struct dentry *parent; | ||
| 1247 | struct inode *inode = NULL; | ||
| 1248 | struct dentry dotdot; | ||
| 1249 | struct fileIdentDesc cfi; | ||
| 1250 | struct udf_fileident_bh fibh; | ||
| 1251 | |||
| 1252 | dotdot.d_name.name = ".."; | ||
| 1253 | dotdot.d_name.len = 2; | ||
| 1254 | |||
| 1255 | lock_kernel(); | ||
| 1256 | if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi)) | ||
| 1257 | goto out_unlock; | ||
| 1258 | |||
| 1259 | if (fibh.sbh != fibh.ebh) | ||
| 1260 | brelse(fibh.ebh); | ||
| 1261 | brelse(fibh.sbh); | ||
| 1262 | |||
| 1263 | inode = udf_iget(child->d_inode->i_sb, | ||
| 1264 | lelb_to_cpu(cfi.icb.extLocation)); | ||
| 1265 | if (!inode) | ||
| 1266 | goto out_unlock; | ||
| 1267 | unlock_kernel(); | ||
| 1268 | |||
| 1269 | parent = d_alloc_anon(inode); | ||
| 1270 | if (!parent) { | ||
| 1271 | iput(inode); | ||
| 1272 | parent = ERR_PTR(-ENOMEM); | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | return parent; | ||
| 1276 | out_unlock: | ||
| 1277 | unlock_kernel(); | ||
| 1278 | return ERR_PTR(-EACCES); | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | |||
| 1282 | static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block, | ||
| 1283 | u16 partref, __u32 generation) | ||
| 1284 | { | ||
| 1285 | struct inode *inode; | ||
| 1286 | struct dentry *result; | ||
| 1287 | kernel_lb_addr loc; | ||
| 1288 | |||
| 1289 | if (block == 0) | ||
| 1290 | return ERR_PTR(-ESTALE); | ||
| 1291 | |||
| 1292 | loc.logicalBlockNum = block; | ||
| 1293 | loc.partitionReferenceNum = partref; | ||
| 1294 | inode = udf_iget(sb, loc); | ||
| 1295 | |||
| 1296 | if (inode == NULL) | ||
| 1297 | return ERR_PTR(-ENOMEM); | ||
| 1298 | |||
| 1299 | if (generation && inode->i_generation != generation) { | ||
| 1300 | iput(inode); | ||
| 1301 | return ERR_PTR(-ESTALE); | ||
| 1302 | } | ||
| 1303 | result = d_alloc_anon(inode); | ||
| 1304 | if (!result) { | ||
| 1305 | iput(inode); | ||
| 1306 | return ERR_PTR(-ENOMEM); | ||
| 1307 | } | ||
| 1308 | return result; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | static struct dentry *udf_fh_to_dentry(struct super_block *sb, | ||
| 1312 | struct fid *fid, int fh_len, int fh_type) | ||
| 1313 | { | ||
| 1314 | if ((fh_len != 3 && fh_len != 5) || | ||
| 1315 | (fh_type != FILEID_UDF_WITH_PARENT && | ||
| 1316 | fh_type != FILEID_UDF_WITHOUT_PARENT)) | ||
| 1317 | return NULL; | ||
| 1318 | |||
| 1319 | return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref, | ||
| 1320 | fid->udf.generation); | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | static struct dentry *udf_fh_to_parent(struct super_block *sb, | ||
| 1324 | struct fid *fid, int fh_len, int fh_type) | ||
| 1325 | { | ||
| 1326 | if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT) | ||
| 1327 | return NULL; | ||
| 1328 | |||
| 1329 | return udf_nfs_get_inode(sb, fid->udf.parent_block, | ||
| 1330 | fid->udf.parent_partref, | ||
| 1331 | fid->udf.parent_generation); | ||
| 1332 | } | ||
| 1333 | static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, | ||
| 1334 | int connectable) | ||
| 1335 | { | ||
| 1336 | int len = *lenp; | ||
| 1337 | struct inode *inode = de->d_inode; | ||
| 1338 | kernel_lb_addr location = UDF_I(inode)->i_location; | ||
| 1339 | struct fid *fid = (struct fid *)fh; | ||
| 1340 | int type = FILEID_UDF_WITHOUT_PARENT; | ||
| 1341 | |||
| 1342 | if (len < 3 || (connectable && len < 5)) | ||
| 1343 | return 255; | ||
| 1344 | |||
| 1345 | *lenp = 3; | ||
| 1346 | fid->udf.block = location.logicalBlockNum; | ||
| 1347 | fid->udf.partref = location.partitionReferenceNum; | ||
| 1348 | fid->udf.generation = inode->i_generation; | ||
| 1349 | |||
| 1350 | if (connectable && !S_ISDIR(inode->i_mode)) { | ||
| 1351 | spin_lock(&de->d_lock); | ||
| 1352 | inode = de->d_parent->d_inode; | ||
| 1353 | location = UDF_I(inode)->i_location; | ||
| 1354 | fid->udf.parent_block = location.logicalBlockNum; | ||
| 1355 | fid->udf.parent_partref = location.partitionReferenceNum; | ||
| 1356 | fid->udf.parent_generation = inode->i_generation; | ||
| 1357 | spin_unlock(&de->d_lock); | ||
| 1358 | *lenp = 5; | ||
| 1359 | type = FILEID_UDF_WITH_PARENT; | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | return type; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | const struct export_operations udf_export_ops = { | ||
| 1366 | .encode_fh = udf_encode_fh, | ||
| 1367 | .fh_to_dentry = udf_fh_to_dentry, | ||
| 1368 | .fh_to_parent = udf_fh_to_parent, | ||
| 1369 | .get_parent = udf_get_parent, | ||
| 1370 | }; | ||
| 1371 | |||
| 1235 | const struct inode_operations udf_dir_inode_operations = { | 1372 | const struct inode_operations udf_dir_inode_operations = { |
| 1236 | .lookup = udf_lookup, | 1373 | .lookup = udf_lookup, |
| 1237 | .create = udf_create, | 1374 | .create = udf_create, |
diff --git a/fs/udf/partition.c b/fs/udf/partition.c index 63610f026ae1..96dfd207c3d6 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c | |||
| @@ -27,8 +27,8 @@ | |||
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/buffer_head.h> | 28 | #include <linux/buffer_head.h> |
| 29 | 29 | ||
| 30 | inline uint32_t udf_get_pblock(struct super_block *sb, uint32_t block, | 30 | uint32_t udf_get_pblock(struct super_block *sb, uint32_t block, |
| 31 | uint16_t partition, uint32_t offset) | 31 | uint16_t partition, uint32_t offset) |
| 32 | { | 32 | { |
| 33 | struct udf_sb_info *sbi = UDF_SB(sb); | 33 | struct udf_sb_info *sbi = UDF_SB(sb); |
| 34 | struct udf_part_map *map; | 34 | struct udf_part_map *map; |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 9fb18a340fc1..7a5f69be6ac2 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -1933,6 +1933,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
| 1933 | 1933 | ||
| 1934 | /* Fill in the rest of the superblock */ | 1934 | /* Fill in the rest of the superblock */ |
| 1935 | sb->s_op = &udf_sb_ops; | 1935 | sb->s_op = &udf_sb_ops; |
| 1936 | sb->s_export_op = &udf_export_ops; | ||
| 1936 | sb->dq_op = NULL; | 1937 | sb->dq_op = NULL; |
| 1937 | sb->s_dirt = 0; | 1938 | sb->s_dirt = 0; |
| 1938 | sb->s_magic = UDF_SUPER_MAGIC; | 1939 | sb->s_magic = UDF_SUPER_MAGIC; |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index f3f45d029277..8fa9c2d70911 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
| @@ -73,6 +73,7 @@ struct task_struct; | |||
| 73 | struct buffer_head; | 73 | struct buffer_head; |
| 74 | struct super_block; | 74 | struct super_block; |
| 75 | 75 | ||
| 76 | extern const struct export_operations udf_export_ops; | ||
| 76 | extern const struct inode_operations udf_dir_inode_operations; | 77 | extern const struct inode_operations udf_dir_inode_operations; |
| 77 | extern const struct file_operations udf_dir_operations; | 78 | extern const struct file_operations udf_dir_operations; |
| 78 | extern const struct inode_operations udf_file_inode_operations; | 79 | extern const struct inode_operations udf_file_inode_operations; |
