diff options
84 files changed, 1326 insertions, 639 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 7f647e17830c..0f103e39b4f6 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
| @@ -138,8 +138,8 @@ evict_inode: | |||
| 138 | put_super: write | 138 | put_super: write |
| 139 | write_super: read | 139 | write_super: read |
| 140 | sync_fs: read | 140 | sync_fs: read |
| 141 | freeze_fs: read | 141 | freeze_fs: write |
| 142 | unfreeze_fs: read | 142 | unfreeze_fs: write |
| 143 | statfs: maybe(read) (see below) | 143 | statfs: maybe(read) (see below) |
| 144 | remount_fs: write | 144 | remount_fs: write |
| 145 | umount_begin: no | 145 | umount_begin: no |
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt index 8c235b6e4246..88152f214f48 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt | |||
| @@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs: | |||
| 32 | - nr_open | 32 | - nr_open |
| 33 | - overflowuid | 33 | - overflowuid |
| 34 | - overflowgid | 34 | - overflowgid |
| 35 | - protected_hardlinks | ||
| 36 | - protected_symlinks | ||
| 35 | - suid_dumpable | 37 | - suid_dumpable |
| 36 | - super-max | 38 | - super-max |
| 37 | - super-nr | 39 | - super-nr |
| @@ -157,6 +159,46 @@ The default is 65534. | |||
| 157 | 159 | ||
| 158 | ============================================================== | 160 | ============================================================== |
| 159 | 161 | ||
| 162 | protected_hardlinks: | ||
| 163 | |||
| 164 | A long-standing class of security issues is the hardlink-based | ||
| 165 | time-of-check-time-of-use race, most commonly seen in world-writable | ||
| 166 | directories like /tmp. The common method of exploitation of this flaw | ||
| 167 | is to cross privilege boundaries when following a given hardlink (i.e. a | ||
| 168 | root process follows a hardlink created by another user). Additionally, | ||
| 169 | on systems without separated partitions, this stops unauthorized users | ||
| 170 | from "pinning" vulnerable setuid/setgid files against being upgraded by | ||
| 171 | the administrator, or linking to special files. | ||
| 172 | |||
| 173 | When set to "0", hardlink creation behavior is unrestricted. | ||
| 174 | |||
| 175 | When set to "1" hardlinks cannot be created by users if they do not | ||
| 176 | already own the source file, or do not have read/write access to it. | ||
| 177 | |||
| 178 | This protection is based on the restrictions in Openwall and grsecurity. | ||
| 179 | |||
| 180 | ============================================================== | ||
| 181 | |||
| 182 | protected_symlinks: | ||
| 183 | |||
| 184 | A long-standing class of security issues is the symlink-based | ||
| 185 | time-of-check-time-of-use race, most commonly seen in world-writable | ||
| 186 | directories like /tmp. The common method of exploitation of this flaw | ||
| 187 | is to cross privilege boundaries when following a given symlink (i.e. a | ||
| 188 | root process follows a symlink belonging to another user). For a likely | ||
| 189 | incomplete list of hundreds of examples across the years, please see: | ||
| 190 | http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=/tmp | ||
| 191 | |||
| 192 | When set to "0", symlink following behavior is unrestricted. | ||
| 193 | |||
| 194 | When set to "1" symlinks are permitted to be followed only when outside | ||
| 195 | a sticky world-writable directory, or when the uid of the symlink and | ||
| 196 | follower match, or when the directory owner matches the symlink's owner. | ||
| 197 | |||
| 198 | This protection is based on the restrictions in Openwall and grsecurity. | ||
| 199 | |||
| 200 | ============================================================== | ||
| 201 | |||
| 160 | suid_dumpable: | 202 | suid_dumpable: |
| 161 | 203 | ||
| 162 | This value can be used to query and set the core dump mode for setuid | 204 | This value can be used to query and set the core dump mode for setuid |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d544d7816df3..dba1ce235da5 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
| @@ -186,10 +186,13 @@ static void spufs_prune_dir(struct dentry *dir) | |||
| 186 | static int spufs_rmdir(struct inode *parent, struct dentry *dir) | 186 | static int spufs_rmdir(struct inode *parent, struct dentry *dir) |
| 187 | { | 187 | { |
| 188 | /* remove all entries */ | 188 | /* remove all entries */ |
| 189 | int res; | ||
| 189 | spufs_prune_dir(dir); | 190 | spufs_prune_dir(dir); |
| 190 | d_drop(dir); | 191 | d_drop(dir); |
| 191 | 192 | res = simple_rmdir(parent, dir); | |
| 192 | return simple_rmdir(parent, dir); | 193 | /* We have to give up the mm_struct */ |
| 194 | spu_forget(SPUFS_I(dir->d_inode)->i_ctx); | ||
| 195 | return res; | ||
| 193 | } | 196 | } |
| 194 | 197 | ||
| 195 | static int spufs_fill_dir(struct dentry *dir, | 198 | static int spufs_fill_dir(struct dentry *dir, |
| @@ -245,9 +248,6 @@ static int spufs_dir_close(struct inode *inode, struct file *file) | |||
| 245 | mutex_unlock(&parent->i_mutex); | 248 | mutex_unlock(&parent->i_mutex); |
| 246 | WARN_ON(ret); | 249 | WARN_ON(ret); |
| 247 | 250 | ||
| 248 | /* We have to give up the mm_struct */ | ||
| 249 | spu_forget(ctx); | ||
| 250 | |||
| 251 | return dcache_dir_close(inode, file); | 251 | return dcache_dir_close(inode, file); |
| 252 | } | 252 | } |
| 253 | 253 | ||
| @@ -450,28 +450,24 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, | |||
| 450 | struct spu_context *neighbor; | 450 | struct spu_context *neighbor; |
| 451 | struct path path = {.mnt = mnt, .dentry = dentry}; | 451 | struct path path = {.mnt = mnt, .dentry = dentry}; |
| 452 | 452 | ||
| 453 | ret = -EPERM; | ||
| 454 | if ((flags & SPU_CREATE_NOSCHED) && | 453 | if ((flags & SPU_CREATE_NOSCHED) && |
| 455 | !capable(CAP_SYS_NICE)) | 454 | !capable(CAP_SYS_NICE)) |
| 456 | goto out_unlock; | 455 | return -EPERM; |
| 457 | 456 | ||
| 458 | ret = -EINVAL; | ||
| 459 | if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) | 457 | if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) |
| 460 | == SPU_CREATE_ISOLATE) | 458 | == SPU_CREATE_ISOLATE) |
| 461 | goto out_unlock; | 459 | return -EINVAL; |
| 462 | 460 | ||
| 463 | ret = -ENODEV; | ||
| 464 | if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) | 461 | if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) |
| 465 | goto out_unlock; | 462 | return -ENODEV; |
| 466 | 463 | ||
| 467 | gang = NULL; | 464 | gang = NULL; |
| 468 | neighbor = NULL; | 465 | neighbor = NULL; |
| 469 | affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU); | 466 | affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU); |
| 470 | if (affinity) { | 467 | if (affinity) { |
| 471 | gang = SPUFS_I(inode)->i_gang; | 468 | gang = SPUFS_I(inode)->i_gang; |
| 472 | ret = -EINVAL; | ||
| 473 | if (!gang) | 469 | if (!gang) |
| 474 | goto out_unlock; | 470 | return -EINVAL; |
| 475 | mutex_lock(&gang->aff_mutex); | 471 | mutex_lock(&gang->aff_mutex); |
| 476 | neighbor = spufs_assert_affinity(flags, gang, aff_filp); | 472 | neighbor = spufs_assert_affinity(flags, gang, aff_filp); |
| 477 | if (IS_ERR(neighbor)) { | 473 | if (IS_ERR(neighbor)) { |
| @@ -492,22 +488,12 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, | |||
| 492 | } | 488 | } |
| 493 | 489 | ||
| 494 | ret = spufs_context_open(&path); | 490 | ret = spufs_context_open(&path); |
| 495 | if (ret < 0) { | 491 | if (ret < 0) |
| 496 | WARN_ON(spufs_rmdir(inode, dentry)); | 492 | WARN_ON(spufs_rmdir(inode, dentry)); |
| 497 | if (affinity) | ||
| 498 | mutex_unlock(&gang->aff_mutex); | ||
| 499 | mutex_unlock(&inode->i_mutex); | ||
| 500 | spu_forget(SPUFS_I(dentry->d_inode)->i_ctx); | ||
| 501 | goto out; | ||
| 502 | } | ||
| 503 | 493 | ||
| 504 | out_aff_unlock: | 494 | out_aff_unlock: |
| 505 | if (affinity) | 495 | if (affinity) |
| 506 | mutex_unlock(&gang->aff_mutex); | 496 | mutex_unlock(&gang->aff_mutex); |
| 507 | out_unlock: | ||
| 508 | mutex_unlock(&inode->i_mutex); | ||
| 509 | out: | ||
| 510 | dput(dentry); | ||
| 511 | return ret; | 497 | return ret; |
| 512 | } | 498 | } |
| 513 | 499 | ||
| @@ -580,18 +566,13 @@ static int spufs_create_gang(struct inode *inode, | |||
| 580 | int ret; | 566 | int ret; |
| 581 | 567 | ||
| 582 | ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO); | 568 | ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO); |
| 583 | if (ret) | 569 | if (!ret) { |
| 584 | goto out; | 570 | ret = spufs_gang_open(&path); |
| 585 | 571 | if (ret < 0) { | |
| 586 | ret = spufs_gang_open(&path); | 572 | int err = simple_rmdir(inode, dentry); |
| 587 | if (ret < 0) { | 573 | WARN_ON(err); |
| 588 | int err = simple_rmdir(inode, dentry); | 574 | } |
| 589 | WARN_ON(err); | ||
| 590 | } | 575 | } |
| 591 | |||
| 592 | out: | ||
| 593 | mutex_unlock(&inode->i_mutex); | ||
| 594 | dput(dentry); | ||
| 595 | return ret; | 576 | return ret; |
| 596 | } | 577 | } |
| 597 | 578 | ||
| @@ -601,40 +582,32 @@ static struct file_system_type spufs_type; | |||
| 601 | long spufs_create(struct path *path, struct dentry *dentry, | 582 | long spufs_create(struct path *path, struct dentry *dentry, |
| 602 | unsigned int flags, umode_t mode, struct file *filp) | 583 | unsigned int flags, umode_t mode, struct file *filp) |
| 603 | { | 584 | { |
| 585 | struct inode *dir = path->dentry->d_inode; | ||
| 604 | int ret; | 586 | int ret; |
| 605 | 587 | ||
| 606 | ret = -EINVAL; | ||
| 607 | /* check if we are on spufs */ | 588 | /* check if we are on spufs */ |
| 608 | if (path->dentry->d_sb->s_type != &spufs_type) | 589 | if (path->dentry->d_sb->s_type != &spufs_type) |
| 609 | goto out; | 590 | return -EINVAL; |
| 610 | 591 | ||
| 611 | /* don't accept undefined flags */ | 592 | /* don't accept undefined flags */ |
| 612 | if (flags & (~SPU_CREATE_FLAG_ALL)) | 593 | if (flags & (~SPU_CREATE_FLAG_ALL)) |
| 613 | goto out; | 594 | return -EINVAL; |
| 614 | 595 | ||
| 615 | /* only threads can be underneath a gang */ | 596 | /* only threads can be underneath a gang */ |
| 616 | if (path->dentry != path->dentry->d_sb->s_root) { | 597 | if (path->dentry != path->dentry->d_sb->s_root) |
| 617 | if ((flags & SPU_CREATE_GANG) || | 598 | if ((flags & SPU_CREATE_GANG) || !SPUFS_I(dir)->i_gang) |
| 618 | !SPUFS_I(path->dentry->d_inode)->i_gang) | 599 | return -EINVAL; |
| 619 | goto out; | ||
| 620 | } | ||
| 621 | 600 | ||
| 622 | mode &= ~current_umask(); | 601 | mode &= ~current_umask(); |
| 623 | 602 | ||
| 624 | if (flags & SPU_CREATE_GANG) | 603 | if (flags & SPU_CREATE_GANG) |
| 625 | ret = spufs_create_gang(path->dentry->d_inode, | 604 | ret = spufs_create_gang(dir, dentry, path->mnt, mode); |
| 626 | dentry, path->mnt, mode); | ||
| 627 | else | 605 | else |
| 628 | ret = spufs_create_context(path->dentry->d_inode, | 606 | ret = spufs_create_context(dir, dentry, path->mnt, flags, mode, |
| 629 | dentry, path->mnt, flags, mode, | ||
| 630 | filp); | 607 | filp); |
| 631 | if (ret >= 0) | 608 | if (ret >= 0) |
| 632 | fsnotify_mkdir(path->dentry->d_inode, dentry); | 609 | fsnotify_mkdir(dir, dentry); |
| 633 | return ret; | ||
| 634 | 610 | ||
| 635 | out: | ||
| 636 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
| 637 | dput(dentry); | ||
| 638 | return ret; | 611 | return ret; |
| 639 | } | 612 | } |
| 640 | 613 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index 5665dcc382c7..5b7d8ffbf890 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c | |||
| @@ -70,7 +70,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags, | |||
| 70 | ret = PTR_ERR(dentry); | 70 | ret = PTR_ERR(dentry); |
| 71 | if (!IS_ERR(dentry)) { | 71 | if (!IS_ERR(dentry)) { |
| 72 | ret = spufs_create(&path, dentry, flags, mode, neighbor); | 72 | ret = spufs_create(&path, dentry, flags, mode, neighbor); |
| 73 | path_put(&path); | 73 | done_path_create(&path, dentry); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | return ret; | 76 | return ret; |
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index d91a3a0b2325..deb4a456cf83 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
| @@ -156,9 +156,7 @@ static int dev_mkdir(const char *name, umode_t mode) | |||
| 156 | if (!err) | 156 | if (!err) |
| 157 | /* mark as kernel-created inode */ | 157 | /* mark as kernel-created inode */ |
| 158 | dentry->d_inode->i_private = &thread; | 158 | dentry->d_inode->i_private = &thread; |
| 159 | dput(dentry); | 159 | done_path_create(&path, dentry); |
| 160 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
| 161 | path_put(&path); | ||
| 162 | return err; | 160 | return err; |
| 163 | } | 161 | } |
| 164 | 162 | ||
| @@ -218,10 +216,7 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev) | |||
| 218 | /* mark as kernel-created inode */ | 216 | /* mark as kernel-created inode */ |
| 219 | dentry->d_inode->i_private = &thread; | 217 | dentry->d_inode->i_private = &thread; |
| 220 | } | 218 | } |
| 221 | dput(dentry); | 219 | done_path_create(&path, dentry); |
| 222 | |||
| 223 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
| 224 | path_put(&path); | ||
| 225 | return err; | 220 | return err; |
| 226 | } | 221 | } |
| 227 | 222 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 57bf1d7ee80f..9ab24528f9b9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
| @@ -1188,7 +1188,7 @@ exit: | |||
| 1188 | kfree(buf); | 1188 | kfree(buf); |
| 1189 | /* close file before return */ | 1189 | /* close file before return */ |
| 1190 | if (fp) | 1190 | if (fp) |
| 1191 | filp_close(fp, current->files); | 1191 | filp_close(fp, NULL); |
| 1192 | /* restore previous address limit */ | 1192 | /* restore previous address limit */ |
| 1193 | set_fs(old_fs); | 1193 | set_fs(old_fs); |
| 1194 | 1194 | ||
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index 9a60d4cd2184..f545716c666d 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c | |||
| @@ -157,12 +157,7 @@ static int create_worker_threads(struct bcm_mini_adapter *psAdapter) | |||
| 157 | 157 | ||
| 158 | static struct file *open_firmware_file(struct bcm_mini_adapter *Adapter, const char *path) | 158 | static struct file *open_firmware_file(struct bcm_mini_adapter *Adapter, const char *path) |
| 159 | { | 159 | { |
| 160 | struct file *flp = NULL; | 160 | struct file *flp = filp_open(path, O_RDONLY, S_IRWXU); |
| 161 | mm_segment_t oldfs; | ||
| 162 | oldfs = get_fs(); | ||
| 163 | set_fs(get_ds()); | ||
| 164 | flp = filp_open(path, O_RDONLY, S_IRWXU); | ||
| 165 | set_fs(oldfs); | ||
| 166 | if (IS_ERR(flp)) { | 161 | if (IS_ERR(flp)) { |
| 167 | pr_err(DRV_NAME "Unable To Open File %s, err %ld", path, PTR_ERR(flp)); | 162 | pr_err(DRV_NAME "Unable To Open File %s, err %ld", path, PTR_ERR(flp)); |
| 168 | flp = NULL; | 163 | flp = NULL; |
| @@ -183,14 +178,12 @@ static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, u | |||
| 183 | { | 178 | { |
| 184 | int errorno = 0; | 179 | int errorno = 0; |
| 185 | struct file *flp = NULL; | 180 | struct file *flp = NULL; |
| 186 | mm_segment_t oldfs; | ||
| 187 | struct timeval tv = {0}; | 181 | struct timeval tv = {0}; |
| 188 | 182 | ||
| 189 | flp = open_firmware_file(Adapter, path); | 183 | flp = open_firmware_file(Adapter, path); |
| 190 | if (!flp) { | 184 | if (!flp) { |
| 191 | errorno = -ENOENT; | ||
| 192 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path); | 185 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path); |
| 193 | goto exit_download; | 186 | return -ENOENT; |
| 194 | } | 187 | } |
| 195 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path, (unsigned long)flp->f_dentry->d_inode->i_size, loc); | 188 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path, (unsigned long)flp->f_dentry->d_inode->i_size, loc); |
| 196 | do_gettimeofday(&tv); | 189 | do_gettimeofday(&tv); |
| @@ -201,10 +194,7 @@ static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, u | |||
| 201 | errorno = -EIO; | 194 | errorno = -EIO; |
| 202 | goto exit_download; | 195 | goto exit_download; |
| 203 | } | 196 | } |
| 204 | oldfs = get_fs(); | ||
| 205 | set_fs(get_ds()); | ||
| 206 | vfs_llseek(flp, 0, 0); | 197 | vfs_llseek(flp, 0, 0); |
| 207 | set_fs(oldfs); | ||
| 208 | if (Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, flp, loc)) { | 198 | if (Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, flp, loc)) { |
| 209 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!"); | 199 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!"); |
| 210 | errorno = -EIO; | 200 | errorno = -EIO; |
| @@ -212,12 +202,7 @@ static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, u | |||
| 212 | } | 202 | } |
| 213 | 203 | ||
| 214 | exit_download: | 204 | exit_download: |
| 215 | oldfs = get_fs(); | 205 | filp_close(flp, NULL); |
| 216 | set_fs(get_ds()); | ||
| 217 | if (flp && !(IS_ERR(flp))) | ||
| 218 | filp_close(flp, current->files); | ||
| 219 | set_fs(oldfs); | ||
| 220 | |||
| 221 | return errorno; | 206 | return errorno; |
| 222 | } | 207 | } |
| 223 | 208 | ||
| @@ -1056,10 +1041,8 @@ OUT: | |||
| 1056 | static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter) | 1041 | static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter) |
| 1057 | { | 1042 | { |
| 1058 | struct file *flp = NULL; | 1043 | struct file *flp = NULL; |
| 1059 | mm_segment_t oldfs = {0}; | ||
| 1060 | char *buff; | 1044 | char *buff; |
| 1061 | int len = 0; | 1045 | int len = 0; |
| 1062 | loff_t pos = 0; | ||
| 1063 | 1046 | ||
| 1064 | buff = kmalloc(BUFFER_1K, GFP_KERNEL); | 1047 | buff = kmalloc(BUFFER_1K, GFP_KERNEL); |
| 1065 | if (!buff) | 1048 | if (!buff) |
| @@ -1079,20 +1062,16 @@ static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter) | |||
| 1079 | Adapter->pstargetparams = NULL; | 1062 | Adapter->pstargetparams = NULL; |
| 1080 | return -ENOENT; | 1063 | return -ENOENT; |
| 1081 | } | 1064 | } |
| 1082 | oldfs = get_fs(); | 1065 | len = kernel_read(flp, 0, buff, BUFFER_1K); |
| 1083 | set_fs(get_ds()); | 1066 | filp_close(flp, NULL); |
| 1084 | len = vfs_read(flp, (void __user __force *)buff, BUFFER_1K, &pos); | ||
| 1085 | set_fs(oldfs); | ||
| 1086 | 1067 | ||
| 1087 | if (len != sizeof(STARGETPARAMS)) { | 1068 | if (len != sizeof(STARGETPARAMS)) { |
| 1088 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Mismatch in Target Param Structure!\n"); | 1069 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Mismatch in Target Param Structure!\n"); |
| 1089 | kfree(buff); | 1070 | kfree(buff); |
| 1090 | kfree(Adapter->pstargetparams); | 1071 | kfree(Adapter->pstargetparams); |
| 1091 | Adapter->pstargetparams = NULL; | 1072 | Adapter->pstargetparams = NULL; |
| 1092 | filp_close(flp, current->files); | ||
| 1093 | return -ENOENT; | 1073 | return -ENOENT; |
| 1094 | } | 1074 | } |
| 1095 | filp_close(flp, current->files); | ||
| 1096 | 1075 | ||
| 1097 | /* Check for autolink in config params */ | 1076 | /* Check for autolink in config params */ |
| 1098 | /* | 1077 | /* |
diff --git a/drivers/staging/gdm72xx/sdio_boot.c b/drivers/staging/gdm72xx/sdio_boot.c index 760efee23d4a..65624bca8b3a 100644 --- a/drivers/staging/gdm72xx/sdio_boot.c +++ b/drivers/staging/gdm72xx/sdio_boot.c | |||
| @@ -66,9 +66,8 @@ static int download_image(struct sdio_func *func, char *img_name) | |||
| 66 | return -ENOENT; | 66 | return -ENOENT; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | if (filp->f_dentry) | 69 | inode = filp->f_dentry->d_inode; |
| 70 | inode = filp->f_dentry->d_inode; | 70 | if (!S_ISREG(inode->i_mode)) { |
| 71 | if (!inode || !S_ISREG(inode->i_mode)) { | ||
| 72 | printk(KERN_ERR "Invalid file type: %s\n", img_name); | 71 | printk(KERN_ERR "Invalid file type: %s\n", img_name); |
| 73 | ret = -EINVAL; | 72 | ret = -EINVAL; |
| 74 | goto out; | 73 | goto out; |
| @@ -123,7 +122,7 @@ static int download_image(struct sdio_func *func, char *img_name) | |||
| 123 | pno++; | 122 | pno++; |
| 124 | } | 123 | } |
| 125 | out: | 124 | out: |
| 126 | filp_close(filp, current->files); | 125 | filp_close(filp, NULL); |
| 127 | return ret; | 126 | return ret; |
| 128 | } | 127 | } |
| 129 | 128 | ||
diff --git a/drivers/staging/gdm72xx/usb_boot.c b/drivers/staging/gdm72xx/usb_boot.c index fef290c38db6..e3dbd5a552ca 100644 --- a/drivers/staging/gdm72xx/usb_boot.c +++ b/drivers/staging/gdm72xx/usb_boot.c | |||
| @@ -173,14 +173,12 @@ int usb_boot(struct usb_device *usbdev, u16 pid) | |||
| 173 | filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0); | 173 | filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0); |
| 174 | if (IS_ERR(filp)) { | 174 | if (IS_ERR(filp)) { |
| 175 | printk(KERN_ERR "Can't find %s.\n", img_name); | 175 | printk(KERN_ERR "Can't find %s.\n", img_name); |
| 176 | set_fs(fs); | ||
| 177 | ret = PTR_ERR(filp); | 176 | ret = PTR_ERR(filp); |
| 178 | goto restore_fs; | 177 | goto restore_fs; |
| 179 | } | 178 | } |
| 180 | 179 | ||
| 181 | if (filp->f_dentry) | 180 | inode = filp->f_dentry->d_inode; |
| 182 | inode = filp->f_dentry->d_inode; | 181 | if (!S_ISREG(inode->i_mode)) { |
| 183 | if (!inode || !S_ISREG(inode->i_mode)) { | ||
| 184 | printk(KERN_ERR "Invalid file type: %s\n", img_name); | 182 | printk(KERN_ERR "Invalid file type: %s\n", img_name); |
| 185 | ret = -EINVAL; | 183 | ret = -EINVAL; |
| 186 | goto out; | 184 | goto out; |
| @@ -262,7 +260,7 @@ int usb_boot(struct usb_device *usbdev, u16 pid) | |||
| 262 | ret = -EINVAL; | 260 | ret = -EINVAL; |
| 263 | } | 261 | } |
| 264 | out: | 262 | out: |
| 265 | filp_close(filp, current->files); | 263 | filp_close(filp, NULL); |
| 266 | 264 | ||
| 267 | restore_fs: | 265 | restore_fs: |
| 268 | set_fs(fs); | 266 | set_fs(fs); |
| @@ -322,13 +320,11 @@ static int em_download_image(struct usb_device *usbdev, char *path, | |||
| 322 | goto restore_fs; | 320 | goto restore_fs; |
| 323 | } | 321 | } |
| 324 | 322 | ||
| 325 | if (filp->f_dentry) { | 323 | inode = filp->f_dentry->d_inode; |
| 326 | inode = filp->f_dentry->d_inode; | 324 | if (!S_ISREG(inode->i_mode)) { |
| 327 | if (!inode || !S_ISREG(inode->i_mode)) { | 325 | printk(KERN_ERR "Invalid file type: %s\n", path); |
| 328 | printk(KERN_ERR "Invalid file type: %s\n", path); | 326 | ret = -EINVAL; |
| 329 | ret = -EINVAL; | 327 | goto out; |
| 330 | goto out; | ||
| 331 | } | ||
| 332 | } | 328 | } |
| 333 | 329 | ||
| 334 | buf = kmalloc(DOWNLOAD_CHUCK + pad_size, GFP_KERNEL); | 330 | buf = kmalloc(DOWNLOAD_CHUCK + pad_size, GFP_KERNEL); |
| @@ -364,7 +360,7 @@ static int em_download_image(struct usb_device *usbdev, char *path, | |||
| 364 | goto out; | 360 | goto out; |
| 365 | 361 | ||
| 366 | out: | 362 | out: |
| 367 | filp_close(filp, current->files); | 363 | filp_close(filp, NULL); |
| 368 | 364 | ||
| 369 | restore_fs: | 365 | restore_fs: |
| 370 | set_fs(fs); | 366 | set_fs(fs); |
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 9e2100551c78..cbb5aaf3e567 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
| @@ -109,46 +109,29 @@ static struct se_device *fd_create_virtdevice( | |||
| 109 | struct se_subsystem_dev *se_dev, | 109 | struct se_subsystem_dev *se_dev, |
| 110 | void *p) | 110 | void *p) |
| 111 | { | 111 | { |
| 112 | char *dev_p = NULL; | ||
| 113 | struct se_device *dev; | 112 | struct se_device *dev; |
| 114 | struct se_dev_limits dev_limits; | 113 | struct se_dev_limits dev_limits; |
| 115 | struct queue_limits *limits; | 114 | struct queue_limits *limits; |
| 116 | struct fd_dev *fd_dev = p; | 115 | struct fd_dev *fd_dev = p; |
| 117 | struct fd_host *fd_host = hba->hba_ptr; | 116 | struct fd_host *fd_host = hba->hba_ptr; |
| 118 | mm_segment_t old_fs; | ||
| 119 | struct file *file; | 117 | struct file *file; |
| 120 | struct inode *inode = NULL; | 118 | struct inode *inode = NULL; |
| 121 | int dev_flags = 0, flags, ret = -EINVAL; | 119 | int dev_flags = 0, flags, ret = -EINVAL; |
| 122 | 120 | ||
| 123 | memset(&dev_limits, 0, sizeof(struct se_dev_limits)); | 121 | memset(&dev_limits, 0, sizeof(struct se_dev_limits)); |
| 124 | 122 | ||
| 125 | old_fs = get_fs(); | ||
| 126 | set_fs(get_ds()); | ||
| 127 | dev_p = getname(fd_dev->fd_dev_name); | ||
| 128 | set_fs(old_fs); | ||
| 129 | |||
| 130 | if (IS_ERR(dev_p)) { | ||
| 131 | pr_err("getname(%s) failed: %lu\n", | ||
| 132 | fd_dev->fd_dev_name, IS_ERR(dev_p)); | ||
| 133 | ret = PTR_ERR(dev_p); | ||
| 134 | goto fail; | ||
| 135 | } | ||
| 136 | /* | 123 | /* |
| 137 | * Use O_DSYNC by default instead of O_SYNC to forgo syncing | 124 | * Use O_DSYNC by default instead of O_SYNC to forgo syncing |
| 138 | * of pure timestamp updates. | 125 | * of pure timestamp updates. |
| 139 | */ | 126 | */ |
| 140 | flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; | 127 | flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; |
| 141 | 128 | ||
| 142 | file = filp_open(dev_p, flags, 0600); | 129 | file = filp_open(fd_dev->fd_dev_name, flags, 0600); |
| 143 | if (IS_ERR(file)) { | 130 | if (IS_ERR(file)) { |
| 144 | pr_err("filp_open(%s) failed\n", dev_p); | 131 | pr_err("filp_open(%s) failed\n", fd_dev->fd_dev_name); |
| 145 | ret = PTR_ERR(file); | 132 | ret = PTR_ERR(file); |
| 146 | goto fail; | 133 | goto fail; |
| 147 | } | 134 | } |
| 148 | if (!file || !file->f_dentry) { | ||
| 149 | pr_err("filp_open(%s) failed\n", dev_p); | ||
| 150 | goto fail; | ||
| 151 | } | ||
| 152 | fd_dev->fd_file = file; | 135 | fd_dev->fd_file = file; |
| 153 | /* | 136 | /* |
| 154 | * If using a block backend with this struct file, we extract | 137 | * If using a block backend with this struct file, we extract |
| @@ -212,14 +195,12 @@ static struct se_device *fd_create_virtdevice( | |||
| 212 | " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, | 195 | " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, |
| 213 | fd_dev->fd_dev_name, fd_dev->fd_dev_size); | 196 | fd_dev->fd_dev_name, fd_dev->fd_dev_size); |
| 214 | 197 | ||
| 215 | putname(dev_p); | ||
| 216 | return dev; | 198 | return dev; |
| 217 | fail: | 199 | fail: |
| 218 | if (fd_dev->fd_file) { | 200 | if (fd_dev->fd_file) { |
| 219 | filp_close(fd_dev->fd_file, NULL); | 201 | filp_close(fd_dev->fd_file, NULL); |
| 220 | fd_dev->fd_file = NULL; | 202 | fd_dev->fd_file = NULL; |
| 221 | } | 203 | } |
| 222 | putname(dev_p); | ||
| 223 | return ERR_PTR(ret); | 204 | return ERR_PTR(ret); |
| 224 | } | 205 | } |
| 225 | 206 | ||
| @@ -452,14 +433,11 @@ static ssize_t fd_set_configfs_dev_params( | |||
| 452 | token = match_token(ptr, tokens, args); | 433 | token = match_token(ptr, tokens, args); |
| 453 | switch (token) { | 434 | switch (token) { |
| 454 | case Opt_fd_dev_name: | 435 | case Opt_fd_dev_name: |
| 455 | arg_p = match_strdup(&args[0]); | 436 | if (match_strlcpy(fd_dev->fd_dev_name, &args[0], |
| 456 | if (!arg_p) { | 437 | FD_MAX_DEV_NAME) == 0) { |
| 457 | ret = -ENOMEM; | 438 | ret = -EINVAL; |
| 458 | break; | 439 | break; |
| 459 | } | 440 | } |
| 460 | snprintf(fd_dev->fd_dev_name, FD_MAX_DEV_NAME, | ||
| 461 | "%s", arg_p); | ||
| 462 | kfree(arg_p); | ||
| 463 | pr_debug("FILEIO: Referencing Path: %s\n", | 441 | pr_debug("FILEIO: Referencing Path: %s\n", |
| 464 | fd_dev->fd_dev_name); | 442 | fd_dev->fd_dev_name); |
| 465 | fd_dev->fbd_flags |= FBDF_HAS_PATH; | 443 | fd_dev->fbd_flags |= FBDF_HAS_PATH; |
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index ae8b18869b8c..8d9bcd8207c8 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c | |||
| @@ -656,9 +656,8 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) | |||
| 656 | if (!(filp->f_mode & FMODE_WRITE)) | 656 | if (!(filp->f_mode & FMODE_WRITE)) |
| 657 | ro = 1; | 657 | ro = 1; |
| 658 | 658 | ||
| 659 | if (filp->f_path.dentry) | 659 | inode = filp->f_path.dentry->d_inode; |
| 660 | inode = filp->f_path.dentry->d_inode; | 660 | if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) { |
| 661 | if (!inode || (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) { | ||
| 662 | LINFO(curlun, "invalid file type: %s\n", filename); | 661 | LINFO(curlun, "invalid file type: %s\n", filename); |
| 663 | goto out; | 662 | goto out; |
| 664 | } | 663 | } |
| @@ -667,7 +666,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) | |||
| 667 | * If we can't read the file, it's no good. | 666 | * If we can't read the file, it's no good. |
| 668 | * If we can't write the file, use it read-only. | 667 | * If we can't write the file, use it read-only. |
| 669 | */ | 668 | */ |
| 670 | if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { | 669 | if (!(filp->f_op->read || filp->f_op->aio_read)) { |
| 671 | LINFO(curlun, "file not readable: %s\n", filename); | 670 | LINFO(curlun, "file not readable: %s\n", filename); |
| 672 | goto out; | 671 | goto out; |
| 673 | } | 672 | } |
| @@ -712,7 +711,6 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) | |||
| 712 | if (fsg_lun_is_open(curlun)) | 711 | if (fsg_lun_is_open(curlun)) |
| 713 | fsg_lun_close(curlun); | 712 | fsg_lun_close(curlun); |
| 714 | 713 | ||
| 715 | get_file(filp); | ||
| 716 | curlun->blksize = blksize; | 714 | curlun->blksize = blksize; |
| 717 | curlun->blkbits = blkbits; | 715 | curlun->blkbits = blkbits; |
| 718 | curlun->ro = ro; | 716 | curlun->ro = ro; |
| @@ -720,10 +718,10 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) | |||
| 720 | curlun->file_length = size; | 718 | curlun->file_length = size; |
| 721 | curlun->num_sectors = num_sectors; | 719 | curlun->num_sectors = num_sectors; |
| 722 | LDBG(curlun, "open backing file: %s\n", filename); | 720 | LDBG(curlun, "open backing file: %s\n", filename); |
| 723 | rc = 0; | 721 | return 0; |
| 724 | 722 | ||
| 725 | out: | 723 | out: |
| 726 | filp_close(filp, current->files); | 724 | fput(filp); |
| 727 | return rc; | 725 | return rc; |
| 728 | } | 726 | } |
| 729 | 727 | ||
diff --git a/drivers/usb/gadget/u_uac1.c b/drivers/usb/gadget/u_uac1.c index af9898982059..e0c5e88e03ed 100644 --- a/drivers/usb/gadget/u_uac1.c +++ b/drivers/usb/gadget/u_uac1.c | |||
| @@ -275,17 +275,17 @@ static int gaudio_close_snd_dev(struct gaudio *gau) | |||
| 275 | /* Close control device */ | 275 | /* Close control device */ |
| 276 | snd = &gau->control; | 276 | snd = &gau->control; |
| 277 | if (snd->filp) | 277 | if (snd->filp) |
| 278 | filp_close(snd->filp, current->files); | 278 | filp_close(snd->filp, NULL); |
| 279 | 279 | ||
| 280 | /* Close PCM playback device and setup substream */ | 280 | /* Close PCM playback device and setup substream */ |
| 281 | snd = &gau->playback; | 281 | snd = &gau->playback; |
| 282 | if (snd->filp) | 282 | if (snd->filp) |
| 283 | filp_close(snd->filp, current->files); | 283 | filp_close(snd->filp, NULL); |
| 284 | 284 | ||
| 285 | /* Close PCM capture device and setup substream */ | 285 | /* Close PCM capture device and setup substream */ |
| 286 | snd = &gau->capture; | 286 | snd = &gau->capture; |
| 287 | if (snd->filp) | 287 | if (snd->filp) |
| 288 | filp_close(snd->filp, current->files); | 288 | filp_close(snd->filp, NULL); |
| 289 | 289 | ||
| 290 | return 0; | 290 | return 0; |
| 291 | } | 291 | } |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 1ddeb11659d4..64cda560c488 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
| @@ -104,6 +104,8 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | |||
| 104 | deferred framebuffer IO. then if userspace touches a page | 104 | deferred framebuffer IO. then if userspace touches a page |
| 105 | again, we repeat the same scheme */ | 105 | again, we repeat the same scheme */ |
| 106 | 106 | ||
| 107 | file_update_time(vma->vm_file); | ||
| 108 | |||
| 107 | /* protect against the workqueue changing the page list */ | 109 | /* protect against the workqueue changing the page list */ |
| 108 | mutex_lock(&fbdefio->lock); | 110 | mutex_lock(&fbdefio->lock); |
| 109 | 111 | ||
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index fc06fd27065e..dd6f7ee1e312 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -610,6 +610,9 @@ v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 610 | p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n", | 610 | p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n", |
| 611 | page, (unsigned long)filp->private_data); | 611 | page, (unsigned long)filp->private_data); |
| 612 | 612 | ||
| 613 | /* Update file times before taking page lock */ | ||
| 614 | file_update_time(filp); | ||
| 615 | |||
| 613 | v9inode = V9FS_I(inode); | 616 | v9inode = V9FS_I(inode); |
| 614 | /* make sure the cache has finished storing the page */ | 617 | /* make sure the cache has finished storing the page */ |
| 615 | v9fs_fscache_wait_on_page_write(inode, page); | 618 | v9fs_fscache_wait_on_page_write(inode, page); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index fadeba6a5db9..62e0cafd6e25 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -1614,8 +1614,6 @@ static int cleaner_kthread(void *arg) | |||
| 1614 | struct btrfs_root *root = arg; | 1614 | struct btrfs_root *root = arg; |
| 1615 | 1615 | ||
| 1616 | do { | 1616 | do { |
| 1617 | vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); | ||
| 1618 | |||
| 1619 | if (!(root->fs_info->sb->s_flags & MS_RDONLY) && | 1617 | if (!(root->fs_info->sb->s_flags & MS_RDONLY) && |
| 1620 | mutex_trylock(&root->fs_info->cleaner_mutex)) { | 1618 | mutex_trylock(&root->fs_info->cleaner_mutex)) { |
| 1621 | btrfs_run_delayed_iputs(root); | 1619 | btrfs_run_delayed_iputs(root); |
| @@ -1647,7 +1645,6 @@ static int transaction_kthread(void *arg) | |||
| 1647 | do { | 1645 | do { |
| 1648 | cannot_commit = false; | 1646 | cannot_commit = false; |
| 1649 | delay = HZ * 30; | 1647 | delay = HZ * 30; |
| 1650 | vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); | ||
| 1651 | mutex_lock(&root->fs_info->transaction_kthread_mutex); | 1648 | mutex_lock(&root->fs_info->transaction_kthread_mutex); |
| 1652 | 1649 | ||
| 1653 | spin_lock(&root->fs_info->trans_lock); | 1650 | spin_lock(&root->fs_info->trans_lock); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 9aa01ec2138d..5caf285c6e4d 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -1379,7 +1379,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1379 | ssize_t err = 0; | 1379 | ssize_t err = 0; |
| 1380 | size_t count, ocount; | 1380 | size_t count, ocount; |
| 1381 | 1381 | ||
| 1382 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 1382 | sb_start_write(inode->i_sb); |
| 1383 | 1383 | ||
| 1384 | mutex_lock(&inode->i_mutex); | 1384 | mutex_lock(&inode->i_mutex); |
| 1385 | 1385 | ||
| @@ -1469,6 +1469,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1469 | num_written = err; | 1469 | num_written = err; |
| 1470 | } | 1470 | } |
| 1471 | out: | 1471 | out: |
| 1472 | sb_end_write(inode->i_sb); | ||
| 1472 | current->backing_dev_info = NULL; | 1473 | current->backing_dev_info = NULL; |
| 1473 | return num_written ? num_written : err; | 1474 | return num_written ? num_written : err; |
| 1474 | } | 1475 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 48bdfd2591c2..83baec24946d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -6629,6 +6629,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 6629 | u64 page_start; | 6629 | u64 page_start; |
| 6630 | u64 page_end; | 6630 | u64 page_end; |
| 6631 | 6631 | ||
| 6632 | sb_start_pagefault(inode->i_sb); | ||
| 6632 | ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); | 6633 | ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); |
| 6633 | if (!ret) { | 6634 | if (!ret) { |
| 6634 | ret = file_update_time(vma->vm_file); | 6635 | ret = file_update_time(vma->vm_file); |
| @@ -6718,12 +6719,15 @@ again: | |||
| 6718 | unlock_extent_cached(io_tree, page_start, page_end, &cached_state, GFP_NOFS); | 6719 | unlock_extent_cached(io_tree, page_start, page_end, &cached_state, GFP_NOFS); |
| 6719 | 6720 | ||
| 6720 | out_unlock: | 6721 | out_unlock: |
| 6721 | if (!ret) | 6722 | if (!ret) { |
| 6723 | sb_end_pagefault(inode->i_sb); | ||
| 6722 | return VM_FAULT_LOCKED; | 6724 | return VM_FAULT_LOCKED; |
| 6725 | } | ||
| 6723 | unlock_page(page); | 6726 | unlock_page(page); |
| 6724 | out: | 6727 | out: |
| 6725 | btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); | 6728 | btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); |
| 6726 | out_noreserve: | 6729 | out_noreserve: |
| 6730 | sb_end_pagefault(inode->i_sb); | ||
| 6727 | return ret; | 6731 | return ret; |
| 6728 | } | 6732 | } |
| 6729 | 6733 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 43f0012016e3..bc2f6ffff3cf 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -195,6 +195,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
| 195 | if (!inode_owner_or_capable(inode)) | 195 | if (!inode_owner_or_capable(inode)) |
| 196 | return -EACCES; | 196 | return -EACCES; |
| 197 | 197 | ||
| 198 | ret = mnt_want_write_file(file); | ||
| 199 | if (ret) | ||
| 200 | return ret; | ||
| 201 | |||
| 198 | mutex_lock(&inode->i_mutex); | 202 | mutex_lock(&inode->i_mutex); |
| 199 | 203 | ||
| 200 | ip_oldflags = ip->flags; | 204 | ip_oldflags = ip->flags; |
| @@ -209,10 +213,6 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
| 209 | } | 213 | } |
| 210 | } | 214 | } |
| 211 | 215 | ||
| 212 | ret = mnt_want_write_file(file); | ||
| 213 | if (ret) | ||
| 214 | goto out_unlock; | ||
| 215 | |||
| 216 | if (flags & FS_SYNC_FL) | 216 | if (flags & FS_SYNC_FL) |
| 217 | ip->flags |= BTRFS_INODE_SYNC; | 217 | ip->flags |= BTRFS_INODE_SYNC; |
| 218 | else | 218 | else |
| @@ -275,9 +275,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
| 275 | inode->i_flags = i_oldflags; | 275 | inode->i_flags = i_oldflags; |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | mnt_drop_write_file(file); | ||
| 279 | out_unlock: | 278 | out_unlock: |
| 280 | mutex_unlock(&inode->i_mutex); | 279 | mutex_unlock(&inode->i_mutex); |
| 280 | mnt_drop_write_file(file); | ||
| 281 | return ret; | 281 | return ret; |
| 282 | } | 282 | } |
| 283 | 283 | ||
| @@ -664,6 +664,10 @@ static noinline int btrfs_mksubvol(struct path *parent, | |||
| 664 | struct dentry *dentry; | 664 | struct dentry *dentry; |
| 665 | int error; | 665 | int error; |
| 666 | 666 | ||
| 667 | error = mnt_want_write(parent->mnt); | ||
| 668 | if (error) | ||
| 669 | return error; | ||
| 670 | |||
| 667 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 671 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
| 668 | 672 | ||
| 669 | dentry = lookup_one_len(name, parent->dentry, namelen); | 673 | dentry = lookup_one_len(name, parent->dentry, namelen); |
| @@ -699,6 +703,7 @@ out_dput: | |||
| 699 | dput(dentry); | 703 | dput(dentry); |
| 700 | out_unlock: | 704 | out_unlock: |
| 701 | mutex_unlock(&dir->i_mutex); | 705 | mutex_unlock(&dir->i_mutex); |
| 706 | mnt_drop_write(parent->mnt); | ||
| 702 | return error; | 707 | return error; |
| 703 | } | 708 | } |
| 704 | 709 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 7ac7cdcc294e..17be3dedacba 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -335,6 +335,8 @@ again: | |||
| 335 | if (!h) | 335 | if (!h) |
| 336 | return ERR_PTR(-ENOMEM); | 336 | return ERR_PTR(-ENOMEM); |
| 337 | 337 | ||
| 338 | sb_start_intwrite(root->fs_info->sb); | ||
| 339 | |||
| 338 | if (may_wait_transaction(root, type)) | 340 | if (may_wait_transaction(root, type)) |
| 339 | wait_current_trans(root); | 341 | wait_current_trans(root); |
| 340 | 342 | ||
| @@ -345,6 +347,7 @@ again: | |||
| 345 | } while (ret == -EBUSY); | 347 | } while (ret == -EBUSY); |
| 346 | 348 | ||
| 347 | if (ret < 0) { | 349 | if (ret < 0) { |
| 350 | sb_end_intwrite(root->fs_info->sb); | ||
| 348 | kmem_cache_free(btrfs_trans_handle_cachep, h); | 351 | kmem_cache_free(btrfs_trans_handle_cachep, h); |
| 349 | return ERR_PTR(ret); | 352 | return ERR_PTR(ret); |
| 350 | } | 353 | } |
| @@ -548,6 +551,8 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
| 548 | btrfs_trans_release_metadata(trans, root); | 551 | btrfs_trans_release_metadata(trans, root); |
| 549 | trans->block_rsv = NULL; | 552 | trans->block_rsv = NULL; |
| 550 | 553 | ||
| 554 | sb_end_intwrite(root->fs_info->sb); | ||
| 555 | |||
| 551 | if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) && | 556 | if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) && |
| 552 | should_end_transaction(trans, root)) { | 557 | should_end_transaction(trans, root)) { |
| 553 | trans->transaction->blocked = 1; | 558 | trans->transaction->blocked = 1; |
| @@ -1578,6 +1583,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1578 | put_transaction(cur_trans); | 1583 | put_transaction(cur_trans); |
| 1579 | put_transaction(cur_trans); | 1584 | put_transaction(cur_trans); |
| 1580 | 1585 | ||
| 1586 | sb_end_intwrite(root->fs_info->sb); | ||
| 1587 | |||
| 1581 | trace_btrfs_transaction_commit(root); | 1588 | trace_btrfs_transaction_commit(root); |
| 1582 | 1589 | ||
| 1583 | btrfs_scrub_continue(root); | 1590 | btrfs_scrub_continue(root); |
diff --git a/fs/buffer.c b/fs/buffer.c index c7062c896d7c..9f6d2e41281d 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -2306,8 +2306,8 @@ EXPORT_SYMBOL(block_commit_write); | |||
| 2306 | * beyond EOF, then the page is guaranteed safe against truncation until we | 2306 | * beyond EOF, then the page is guaranteed safe against truncation until we |
| 2307 | * unlock the page. | 2307 | * unlock the page. |
| 2308 | * | 2308 | * |
| 2309 | * Direct callers of this function should call vfs_check_frozen() so that page | 2309 | * Direct callers of this function should protect against filesystem freezing |
| 2310 | * fault does not busyloop until the fs is thawed. | 2310 | * using sb_start_write() - sb_end_write() functions. |
| 2311 | */ | 2311 | */ |
| 2312 | int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, | 2312 | int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, |
| 2313 | get_block_t get_block) | 2313 | get_block_t get_block) |
| @@ -2318,6 +2318,12 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, | |||
| 2318 | loff_t size; | 2318 | loff_t size; |
| 2319 | int ret; | 2319 | int ret; |
| 2320 | 2320 | ||
| 2321 | /* | ||
| 2322 | * Update file times before taking page lock. We may end up failing the | ||
| 2323 | * fault so this update may be superfluous but who really cares... | ||
| 2324 | */ | ||
| 2325 | file_update_time(vma->vm_file); | ||
| 2326 | |||
| 2321 | lock_page(page); | 2327 | lock_page(page); |
| 2322 | size = i_size_read(inode); | 2328 | size = i_size_read(inode); |
| 2323 | if ((page->mapping != inode->i_mapping) || | 2329 | if ((page->mapping != inode->i_mapping) || |
| @@ -2339,18 +2345,7 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, | |||
| 2339 | 2345 | ||
| 2340 | if (unlikely(ret < 0)) | 2346 | if (unlikely(ret < 0)) |
| 2341 | goto out_unlock; | 2347 | goto out_unlock; |
| 2342 | /* | ||
| 2343 | * Freezing in progress? We check after the page is marked dirty and | ||
| 2344 | * with page lock held so if the test here fails, we are sure freezing | ||
| 2345 | * code will wait during syncing until the page fault is done - at that | ||
| 2346 | * point page will be dirty and unlocked so freezing code will write it | ||
| 2347 | * and writeprotect it again. | ||
| 2348 | */ | ||
| 2349 | set_page_dirty(page); | 2348 | set_page_dirty(page); |
| 2350 | if (inode->i_sb->s_frozen != SB_UNFROZEN) { | ||
| 2351 | ret = -EAGAIN; | ||
| 2352 | goto out_unlock; | ||
| 2353 | } | ||
| 2354 | wait_on_page_writeback(page); | 2349 | wait_on_page_writeback(page); |
| 2355 | return 0; | 2350 | return 0; |
| 2356 | out_unlock: | 2351 | out_unlock: |
| @@ -2365,12 +2360,9 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, | |||
| 2365 | int ret; | 2360 | int ret; |
| 2366 | struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb; | 2361 | struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb; |
| 2367 | 2362 | ||
| 2368 | /* | 2363 | sb_start_pagefault(sb); |
| 2369 | * This check is racy but catches the common case. The check in | ||
| 2370 | * __block_page_mkwrite() is reliable. | ||
| 2371 | */ | ||
| 2372 | vfs_check_frozen(sb, SB_FREEZE_WRITE); | ||
| 2373 | ret = __block_page_mkwrite(vma, vmf, get_block); | 2364 | ret = __block_page_mkwrite(vma, vmf, get_block); |
| 2365 | sb_end_pagefault(sb); | ||
| 2374 | return block_page_mkwrite_return(ret); | 2366 | return block_page_mkwrite_return(ret); |
| 2375 | } | 2367 | } |
| 2376 | EXPORT_SYMBOL(block_page_mkwrite); | 2368 | EXPORT_SYMBOL(block_page_mkwrite); |
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 8b67304e4b80..452e71a1b753 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
| @@ -1184,6 +1184,9 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 1184 | loff_t size, len; | 1184 | loff_t size, len; |
| 1185 | int ret; | 1185 | int ret; |
| 1186 | 1186 | ||
| 1187 | /* Update time before taking page lock */ | ||
| 1188 | file_update_time(vma->vm_file); | ||
| 1189 | |||
| 1187 | size = i_size_read(inode); | 1190 | size = i_size_read(inode); |
| 1188 | if (off + PAGE_CACHE_SIZE <= size) | 1191 | if (off + PAGE_CACHE_SIZE <= size) |
| 1189 | len = PAGE_CACHE_SIZE; | 1192 | len = PAGE_CACHE_SIZE; |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index ffa2be57804d..c3ca12c33ca2 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
| @@ -318,21 +318,20 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry, | |||
| 318 | struct vfsmount *lower_mnt; | 318 | struct vfsmount *lower_mnt; |
| 319 | int rc = 0; | 319 | int rc = 0; |
| 320 | 320 | ||
| 321 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); | ||
| 322 | fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode); | ||
| 323 | BUG_ON(!lower_dentry->d_count); | ||
| 324 | |||
| 325 | dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL); | 321 | dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL); |
| 326 | ecryptfs_set_dentry_private(dentry, dentry_info); | ||
| 327 | if (!dentry_info) { | 322 | if (!dentry_info) { |
| 328 | printk(KERN_ERR "%s: Out of memory whilst attempting " | 323 | printk(KERN_ERR "%s: Out of memory whilst attempting " |
| 329 | "to allocate ecryptfs_dentry_info struct\n", | 324 | "to allocate ecryptfs_dentry_info struct\n", |
| 330 | __func__); | 325 | __func__); |
| 331 | dput(lower_dentry); | 326 | dput(lower_dentry); |
| 332 | mntput(lower_mnt); | ||
| 333 | d_drop(dentry); | ||
| 334 | return -ENOMEM; | 327 | return -ENOMEM; |
| 335 | } | 328 | } |
| 329 | |||
| 330 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); | ||
| 331 | fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode); | ||
| 332 | BUG_ON(!lower_dentry->d_count); | ||
| 333 | |||
| 334 | ecryptfs_set_dentry_private(dentry, dentry_info); | ||
| 336 | ecryptfs_set_dentry_lower(dentry, lower_dentry); | 335 | ecryptfs_set_dentry_lower(dentry, lower_dentry); |
| 337 | ecryptfs_set_dentry_lower_mnt(dentry, lower_mnt); | 336 | ecryptfs_set_dentry_lower_mnt(dentry, lower_mnt); |
| 338 | 337 | ||
| @@ -381,12 +380,6 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
| 381 | struct dentry *lower_dir_dentry, *lower_dentry; | 380 | struct dentry *lower_dir_dentry, *lower_dentry; |
| 382 | int rc = 0; | 381 | int rc = 0; |
| 383 | 382 | ||
| 384 | if ((ecryptfs_dentry->d_name.len == 1 | ||
| 385 | && !strcmp(ecryptfs_dentry->d_name.name, ".")) | ||
| 386 | || (ecryptfs_dentry->d_name.len == 2 | ||
| 387 | && !strcmp(ecryptfs_dentry->d_name.name, ".."))) { | ||
| 388 | goto out_d_drop; | ||
| 389 | } | ||
| 390 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); | 383 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); |
| 391 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); | 384 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); |
| 392 | lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, | 385 | lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, |
| @@ -397,8 +390,8 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
| 397 | rc = PTR_ERR(lower_dentry); | 390 | rc = PTR_ERR(lower_dentry); |
| 398 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 391 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
| 399 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 392 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
| 400 | encrypted_and_encoded_name); | 393 | ecryptfs_dentry->d_name.name); |
| 401 | goto out_d_drop; | 394 | goto out; |
| 402 | } | 395 | } |
| 403 | if (lower_dentry->d_inode) | 396 | if (lower_dentry->d_inode) |
| 404 | goto interpose; | 397 | goto interpose; |
| @@ -415,7 +408,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
| 415 | if (rc) { | 408 | if (rc) { |
| 416 | printk(KERN_ERR "%s: Error attempting to encrypt and encode " | 409 | printk(KERN_ERR "%s: Error attempting to encrypt and encode " |
| 417 | "filename; rc = [%d]\n", __func__, rc); | 410 | "filename; rc = [%d]\n", __func__, rc); |
| 418 | goto out_d_drop; | 411 | goto out; |
| 419 | } | 412 | } |
| 420 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); | 413 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); |
| 421 | lower_dentry = lookup_one_len(encrypted_and_encoded_name, | 414 | lower_dentry = lookup_one_len(encrypted_and_encoded_name, |
| @@ -427,14 +420,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
| 427 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 420 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
| 428 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 421 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
| 429 | encrypted_and_encoded_name); | 422 | encrypted_and_encoded_name); |
| 430 | goto out_d_drop; | 423 | goto out; |
| 431 | } | 424 | } |
| 432 | interpose: | 425 | interpose: |
| 433 | rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry, | 426 | rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry, |
| 434 | ecryptfs_dir_inode); | 427 | ecryptfs_dir_inode); |
| 435 | goto out; | ||
| 436 | out_d_drop: | ||
| 437 | d_drop(ecryptfs_dentry); | ||
| 438 | out: | 428 | out: |
| 439 | kfree(encrypted_and_encoded_name); | 429 | kfree(encrypted_and_encoded_name); |
| 440 | return ERR_PTR(rc); | 430 | return ERR_PTR(rc); |
| @@ -2069,25 +2069,18 @@ static void wait_for_dump_helpers(struct file *file) | |||
| 2069 | */ | 2069 | */ |
| 2070 | static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) | 2070 | static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) |
| 2071 | { | 2071 | { |
| 2072 | struct file *rp, *wp; | 2072 | struct file *files[2]; |
| 2073 | struct fdtable *fdt; | 2073 | struct fdtable *fdt; |
| 2074 | struct coredump_params *cp = (struct coredump_params *)info->data; | 2074 | struct coredump_params *cp = (struct coredump_params *)info->data; |
| 2075 | struct files_struct *cf = current->files; | 2075 | struct files_struct *cf = current->files; |
| 2076 | int err = create_pipe_files(files, 0); | ||
| 2077 | if (err) | ||
| 2078 | return err; | ||
| 2076 | 2079 | ||
| 2077 | wp = create_write_pipe(0); | 2080 | cp->file = files[1]; |
| 2078 | if (IS_ERR(wp)) | ||
| 2079 | return PTR_ERR(wp); | ||
| 2080 | |||
| 2081 | rp = create_read_pipe(wp, 0); | ||
| 2082 | if (IS_ERR(rp)) { | ||
| 2083 | free_write_pipe(wp); | ||
| 2084 | return PTR_ERR(rp); | ||
| 2085 | } | ||
| 2086 | |||
| 2087 | cp->file = wp; | ||
| 2088 | 2081 | ||
| 2089 | sys_close(0); | 2082 | sys_close(0); |
| 2090 | fd_install(0, rp); | 2083 | fd_install(0, files[0]); |
| 2091 | spin_lock(&cf->file_lock); | 2084 | spin_lock(&cf->file_lock); |
| 2092 | fdt = files_fdtable(cf); | 2085 | fdt = files_fdtable(cf); |
| 2093 | __set_open_fd(0, fdt); | 2086 | __set_open_fd(0, fdt); |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 264d315f6c47..6363ac66fafa 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
| @@ -79,6 +79,7 @@ void ext2_evict_inode(struct inode * inode) | |||
| 79 | truncate_inode_pages(&inode->i_data, 0); | 79 | truncate_inode_pages(&inode->i_data, 0); |
| 80 | 80 | ||
| 81 | if (want_delete) { | 81 | if (want_delete) { |
| 82 | sb_start_intwrite(inode->i_sb); | ||
| 82 | /* set dtime */ | 83 | /* set dtime */ |
| 83 | EXT2_I(inode)->i_dtime = get_seconds(); | 84 | EXT2_I(inode)->i_dtime = get_seconds(); |
| 84 | mark_inode_dirty(inode); | 85 | mark_inode_dirty(inode); |
| @@ -98,8 +99,10 @@ void ext2_evict_inode(struct inode * inode) | |||
| 98 | if (unlikely(rsv)) | 99 | if (unlikely(rsv)) |
| 99 | kfree(rsv); | 100 | kfree(rsv); |
| 100 | 101 | ||
| 101 | if (want_delete) | 102 | if (want_delete) { |
| 102 | ext2_free_inode(inode); | 103 | ext2_free_inode(inode); |
| 104 | sb_end_intwrite(inode->i_sb); | ||
| 105 | } | ||
| 103 | } | 106 | } |
| 104 | 107 | ||
| 105 | typedef struct { | 108 | typedef struct { |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 9f311d27b16f..af74d9e27b71 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
| @@ -42,6 +42,8 @@ static void ext2_sync_super(struct super_block *sb, | |||
| 42 | static int ext2_remount (struct super_block * sb, int * flags, char * data); | 42 | static int ext2_remount (struct super_block * sb, int * flags, char * data); |
| 43 | static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); | 43 | static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); |
| 44 | static int ext2_sync_fs(struct super_block *sb, int wait); | 44 | static int ext2_sync_fs(struct super_block *sb, int wait); |
| 45 | static int ext2_freeze(struct super_block *sb); | ||
| 46 | static int ext2_unfreeze(struct super_block *sb); | ||
| 45 | 47 | ||
| 46 | void ext2_error(struct super_block *sb, const char *function, | 48 | void ext2_error(struct super_block *sb, const char *function, |
| 47 | const char *fmt, ...) | 49 | const char *fmt, ...) |
| @@ -305,6 +307,8 @@ static const struct super_operations ext2_sops = { | |||
| 305 | .evict_inode = ext2_evict_inode, | 307 | .evict_inode = ext2_evict_inode, |
| 306 | .put_super = ext2_put_super, | 308 | .put_super = ext2_put_super, |
| 307 | .sync_fs = ext2_sync_fs, | 309 | .sync_fs = ext2_sync_fs, |
| 310 | .freeze_fs = ext2_freeze, | ||
| 311 | .unfreeze_fs = ext2_unfreeze, | ||
| 308 | .statfs = ext2_statfs, | 312 | .statfs = ext2_statfs, |
| 309 | .remount_fs = ext2_remount, | 313 | .remount_fs = ext2_remount, |
| 310 | .show_options = ext2_show_options, | 314 | .show_options = ext2_show_options, |
| @@ -1200,6 +1204,35 @@ static int ext2_sync_fs(struct super_block *sb, int wait) | |||
| 1200 | return 0; | 1204 | return 0; |
| 1201 | } | 1205 | } |
| 1202 | 1206 | ||
| 1207 | static int ext2_freeze(struct super_block *sb) | ||
| 1208 | { | ||
| 1209 | struct ext2_sb_info *sbi = EXT2_SB(sb); | ||
| 1210 | |||
| 1211 | /* | ||
| 1212 | * Open but unlinked files present? Keep EXT2_VALID_FS flag cleared | ||
| 1213 | * because we have unattached inodes and thus filesystem is not fully | ||
| 1214 | * consistent. | ||
| 1215 | */ | ||
| 1216 | if (atomic_long_read(&sb->s_remove_count)) { | ||
| 1217 | ext2_sync_fs(sb, 1); | ||
| 1218 | return 0; | ||
| 1219 | } | ||
| 1220 | /* Set EXT2_FS_VALID flag */ | ||
| 1221 | spin_lock(&sbi->s_lock); | ||
| 1222 | sbi->s_es->s_state = cpu_to_le16(sbi->s_mount_state); | ||
| 1223 | spin_unlock(&sbi->s_lock); | ||
| 1224 | ext2_sync_super(sb, sbi->s_es, 1); | ||
| 1225 | |||
| 1226 | return 0; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | static int ext2_unfreeze(struct super_block *sb) | ||
| 1230 | { | ||
| 1231 | /* Just write sb to clear EXT2_VALID_FS flag */ | ||
| 1232 | ext2_write_super(sb); | ||
| 1233 | |||
| 1234 | return 0; | ||
| 1235 | } | ||
| 1203 | 1236 | ||
| 1204 | void ext2_write_super(struct super_block *sb) | 1237 | void ext2_write_super(struct super_block *sb) |
| 1205 | { | 1238 | { |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 89b59cb7f9b8..6324f74e0342 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -233,6 +233,11 @@ void ext4_evict_inode(struct inode *inode) | |||
| 233 | if (is_bad_inode(inode)) | 233 | if (is_bad_inode(inode)) |
| 234 | goto no_delete; | 234 | goto no_delete; |
| 235 | 235 | ||
| 236 | /* | ||
| 237 | * Protect us against freezing - iput() caller didn't have to have any | ||
| 238 | * protection against it | ||
| 239 | */ | ||
| 240 | sb_start_intwrite(inode->i_sb); | ||
| 236 | handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3); | 241 | handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3); |
| 237 | if (IS_ERR(handle)) { | 242 | if (IS_ERR(handle)) { |
| 238 | ext4_std_error(inode->i_sb, PTR_ERR(handle)); | 243 | ext4_std_error(inode->i_sb, PTR_ERR(handle)); |
| @@ -242,6 +247,7 @@ void ext4_evict_inode(struct inode *inode) | |||
| 242 | * cleaned up. | 247 | * cleaned up. |
| 243 | */ | 248 | */ |
| 244 | ext4_orphan_del(NULL, inode); | 249 | ext4_orphan_del(NULL, inode); |
| 250 | sb_end_intwrite(inode->i_sb); | ||
| 245 | goto no_delete; | 251 | goto no_delete; |
| 246 | } | 252 | } |
| 247 | 253 | ||
| @@ -273,6 +279,7 @@ void ext4_evict_inode(struct inode *inode) | |||
| 273 | stop_handle: | 279 | stop_handle: |
| 274 | ext4_journal_stop(handle); | 280 | ext4_journal_stop(handle); |
| 275 | ext4_orphan_del(NULL, inode); | 281 | ext4_orphan_del(NULL, inode); |
| 282 | sb_end_intwrite(inode->i_sb); | ||
| 276 | goto no_delete; | 283 | goto no_delete; |
| 277 | } | 284 | } |
| 278 | } | 285 | } |
| @@ -301,6 +308,7 @@ void ext4_evict_inode(struct inode *inode) | |||
| 301 | else | 308 | else |
| 302 | ext4_free_inode(handle, inode); | 309 | ext4_free_inode(handle, inode); |
| 303 | ext4_journal_stop(handle); | 310 | ext4_journal_stop(handle); |
| 311 | sb_end_intwrite(inode->i_sb); | ||
| 304 | return; | 312 | return; |
| 305 | no_delete: | 313 | no_delete: |
| 306 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ | 314 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ |
| @@ -4779,11 +4787,7 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 4779 | get_block_t *get_block; | 4787 | get_block_t *get_block; |
| 4780 | int retries = 0; | 4788 | int retries = 0; |
| 4781 | 4789 | ||
| 4782 | /* | 4790 | sb_start_pagefault(inode->i_sb); |
| 4783 | * This check is racy but catches the common case. We rely on | ||
| 4784 | * __block_page_mkwrite() to do a reliable check. | ||
| 4785 | */ | ||
| 4786 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
| 4787 | /* Delalloc case is easy... */ | 4791 | /* Delalloc case is easy... */ |
| 4788 | if (test_opt(inode->i_sb, DELALLOC) && | 4792 | if (test_opt(inode->i_sb, DELALLOC) && |
| 4789 | !ext4_should_journal_data(inode) && | 4793 | !ext4_should_journal_data(inode) && |
| @@ -4851,5 +4855,6 @@ retry_alloc: | |||
| 4851 | out_ret: | 4855 | out_ret: |
| 4852 | ret = block_page_mkwrite_return(ret); | 4856 | ret = block_page_mkwrite_return(ret); |
| 4853 | out: | 4857 | out: |
| 4858 | sb_end_pagefault(inode->i_sb); | ||
| 4854 | return ret; | 4859 | return ret; |
| 4855 | } | 4860 | } |
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index f99a1311e847..fe7c63f4717e 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c | |||
| @@ -44,6 +44,11 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) | |||
| 44 | { | 44 | { |
| 45 | struct mmp_struct *mmp = (struct mmp_struct *)(bh->b_data); | 45 | struct mmp_struct *mmp = (struct mmp_struct *)(bh->b_data); |
| 46 | 46 | ||
| 47 | /* | ||
| 48 | * We protect against freezing so that we don't create dirty buffers | ||
| 49 | * on frozen filesystem. | ||
| 50 | */ | ||
| 51 | sb_start_write(sb); | ||
| 47 | ext4_mmp_csum_set(sb, mmp); | 52 | ext4_mmp_csum_set(sb, mmp); |
| 48 | mark_buffer_dirty(bh); | 53 | mark_buffer_dirty(bh); |
| 49 | lock_buffer(bh); | 54 | lock_buffer(bh); |
| @@ -51,6 +56,7 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) | |||
| 51 | get_bh(bh); | 56 | get_bh(bh); |
| 52 | submit_bh(WRITE_SYNC, bh); | 57 | submit_bh(WRITE_SYNC, bh); |
| 53 | wait_on_buffer(bh); | 58 | wait_on_buffer(bh); |
| 59 | sb_end_write(sb); | ||
| 54 | if (unlikely(!buffer_uptodate(bh))) | 60 | if (unlikely(!buffer_uptodate(bh))) |
| 55 | return 1; | 61 | return 1; |
| 56 | 62 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 2d51cd9af225..d76ec8277d3f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -331,33 +331,17 @@ static void ext4_put_nojournal(handle_t *handle) | |||
| 331 | * journal_end calls result in the superblock being marked dirty, so | 331 | * journal_end calls result in the superblock being marked dirty, so |
| 332 | * that sync() will call the filesystem's write_super callback if | 332 | * that sync() will call the filesystem's write_super callback if |
| 333 | * appropriate. | 333 | * appropriate. |
| 334 | * | ||
| 335 | * To avoid j_barrier hold in userspace when a user calls freeze(), | ||
| 336 | * ext4 prevents a new handle from being started by s_frozen, which | ||
| 337 | * is in an upper layer. | ||
| 338 | */ | 334 | */ |
| 339 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | 335 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) |
| 340 | { | 336 | { |
| 341 | journal_t *journal; | 337 | journal_t *journal; |
| 342 | handle_t *handle; | ||
| 343 | 338 | ||
| 344 | trace_ext4_journal_start(sb, nblocks, _RET_IP_); | 339 | trace_ext4_journal_start(sb, nblocks, _RET_IP_); |
| 345 | if (sb->s_flags & MS_RDONLY) | 340 | if (sb->s_flags & MS_RDONLY) |
| 346 | return ERR_PTR(-EROFS); | 341 | return ERR_PTR(-EROFS); |
| 347 | 342 | ||
| 343 | WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); | ||
| 348 | journal = EXT4_SB(sb)->s_journal; | 344 | journal = EXT4_SB(sb)->s_journal; |
| 349 | handle = ext4_journal_current_handle(); | ||
| 350 | |||
| 351 | /* | ||
| 352 | * If a handle has been started, it should be allowed to | ||
| 353 | * finish, otherwise deadlock could happen between freeze | ||
| 354 | * and others(e.g. truncate) due to the restart of the | ||
| 355 | * journal handle if the filesystem is forzen and active | ||
| 356 | * handles are not stopped. | ||
| 357 | */ | ||
| 358 | if (!handle) | ||
| 359 | vfs_check_frozen(sb, SB_FREEZE_TRANS); | ||
| 360 | |||
| 361 | if (!journal) | 345 | if (!journal) |
| 362 | return ext4_get_nojournal(); | 346 | return ext4_get_nojournal(); |
| 363 | /* | 347 | /* |
| @@ -2747,6 +2731,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr) | |||
| 2747 | sb = elr->lr_super; | 2731 | sb = elr->lr_super; |
| 2748 | ngroups = EXT4_SB(sb)->s_groups_count; | 2732 | ngroups = EXT4_SB(sb)->s_groups_count; |
| 2749 | 2733 | ||
| 2734 | sb_start_write(sb); | ||
| 2750 | for (group = elr->lr_next_group; group < ngroups; group++) { | 2735 | for (group = elr->lr_next_group; group < ngroups; group++) { |
| 2751 | gdp = ext4_get_group_desc(sb, group, NULL); | 2736 | gdp = ext4_get_group_desc(sb, group, NULL); |
| 2752 | if (!gdp) { | 2737 | if (!gdp) { |
| @@ -2773,6 +2758,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr) | |||
| 2773 | elr->lr_next_sched = jiffies + elr->lr_timeout; | 2758 | elr->lr_next_sched = jiffies + elr->lr_timeout; |
| 2774 | elr->lr_next_group = group + 1; | 2759 | elr->lr_next_group = group + 1; |
| 2775 | } | 2760 | } |
| 2761 | sb_end_write(sb); | ||
| 2776 | 2762 | ||
| 2777 | return ret; | 2763 | return ret; |
| 2778 | } | 2764 | } |
| @@ -4460,10 +4446,8 @@ int ext4_force_commit(struct super_block *sb) | |||
| 4460 | return 0; | 4446 | return 0; |
| 4461 | 4447 | ||
| 4462 | journal = EXT4_SB(sb)->s_journal; | 4448 | journal = EXT4_SB(sb)->s_journal; |
| 4463 | if (journal) { | 4449 | if (journal) |
| 4464 | vfs_check_frozen(sb, SB_FREEZE_TRANS); | ||
| 4465 | ret = ext4_journal_force_commit(journal); | 4450 | ret = ext4_journal_force_commit(journal); |
| 4466 | } | ||
| 4467 | 4451 | ||
| 4468 | return ret; | 4452 | return ret; |
| 4469 | } | 4453 | } |
| @@ -4493,9 +4477,8 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
| 4493 | * gives us a chance to flush the journal completely and mark the fs clean. | 4477 | * gives us a chance to flush the journal completely and mark the fs clean. |
| 4494 | * | 4478 | * |
| 4495 | * Note that only this function cannot bring a filesystem to be in a clean | 4479 | * Note that only this function cannot bring a filesystem to be in a clean |
| 4496 | * state independently, because ext4 prevents a new handle from being started | 4480 | * state independently. It relies on upper layer to stop all data & metadata |
| 4497 | * by @sb->s_frozen, which stays in an upper layer. It thus needs help from | 4481 | * modifications. |
| 4498 | * the upper layer. | ||
| 4499 | */ | 4482 | */ |
| 4500 | static int ext4_freeze(struct super_block *sb) | 4483 | static int ext4_freeze(struct super_block *sb) |
| 4501 | { | 4484 | { |
| @@ -4522,7 +4505,7 @@ static int ext4_freeze(struct super_block *sb) | |||
| 4522 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 4505 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
| 4523 | error = ext4_commit_super(sb, 1); | 4506 | error = ext4_commit_super(sb, 1); |
| 4524 | out: | 4507 | out: |
| 4525 | /* we rely on s_frozen to stop further updates */ | 4508 | /* we rely on upper layer to stop further updates */ |
| 4526 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 4509 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
| 4527 | return error; | 4510 | return error; |
| 4528 | } | 4511 | } |
diff --git a/fs/fat/file.c b/fs/fat/file.c index a71fe3715ee8..e007b8bd8e5e 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
| @@ -43,10 +43,10 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr) | |||
| 43 | if (err) | 43 | if (err) |
| 44 | goto out; | 44 | goto out; |
| 45 | 45 | ||
| 46 | mutex_lock(&inode->i_mutex); | ||
| 47 | err = mnt_want_write_file(file); | 46 | err = mnt_want_write_file(file); |
| 48 | if (err) | 47 | if (err) |
| 49 | goto out_unlock_inode; | 48 | goto out; |
| 49 | mutex_lock(&inode->i_mutex); | ||
| 50 | 50 | ||
| 51 | /* | 51 | /* |
| 52 | * ATTR_VOLUME and ATTR_DIR cannot be changed; this also | 52 | * ATTR_VOLUME and ATTR_DIR cannot be changed; this also |
| @@ -73,14 +73,14 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr) | |||
| 73 | /* The root directory has no attributes */ | 73 | /* The root directory has no attributes */ |
| 74 | if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) { | 74 | if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) { |
| 75 | err = -EINVAL; | 75 | err = -EINVAL; |
| 76 | goto out_drop_write; | 76 | goto out_unlock_inode; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | if (sbi->options.sys_immutable && | 79 | if (sbi->options.sys_immutable && |
| 80 | ((attr | oldattr) & ATTR_SYS) && | 80 | ((attr | oldattr) & ATTR_SYS) && |
| 81 | !capable(CAP_LINUX_IMMUTABLE)) { | 81 | !capable(CAP_LINUX_IMMUTABLE)) { |
| 82 | err = -EPERM; | 82 | err = -EPERM; |
| 83 | goto out_drop_write; | 83 | goto out_unlock_inode; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | /* | 86 | /* |
| @@ -90,12 +90,12 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr) | |||
| 90 | */ | 90 | */ |
| 91 | err = security_inode_setattr(file->f_path.dentry, &ia); | 91 | err = security_inode_setattr(file->f_path.dentry, &ia); |
| 92 | if (err) | 92 | if (err) |
| 93 | goto out_drop_write; | 93 | goto out_unlock_inode; |
| 94 | 94 | ||
| 95 | /* This MUST be done before doing anything irreversible... */ | 95 | /* This MUST be done before doing anything irreversible... */ |
| 96 | err = fat_setattr(file->f_path.dentry, &ia); | 96 | err = fat_setattr(file->f_path.dentry, &ia); |
| 97 | if (err) | 97 | if (err) |
| 98 | goto out_drop_write; | 98 | goto out_unlock_inode; |
| 99 | 99 | ||
| 100 | fsnotify_change(file->f_path.dentry, ia.ia_valid); | 100 | fsnotify_change(file->f_path.dentry, ia.ia_valid); |
| 101 | if (sbi->options.sys_immutable) { | 101 | if (sbi->options.sys_immutable) { |
| @@ -107,10 +107,9 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr) | |||
| 107 | 107 | ||
| 108 | fat_save_attrs(inode, attr); | 108 | fat_save_attrs(inode, attr); |
| 109 | mark_inode_dirty(inode); | 109 | mark_inode_dirty(inode); |
| 110 | out_drop_write: | ||
| 111 | mnt_drop_write_file(file); | ||
| 112 | out_unlock_inode: | 110 | out_unlock_inode: |
| 113 | mutex_unlock(&inode->i_mutex); | 111 | mutex_unlock(&inode->i_mutex); |
| 112 | mnt_drop_write_file(file); | ||
| 114 | out: | 113 | out: |
| 115 | return err; | 114 | return err; |
| 116 | } | 115 | } |
diff --git a/fs/file_table.c b/fs/file_table.c index b3fc4d67a26b..701985e4ccda 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -43,7 +43,7 @@ static struct kmem_cache *filp_cachep __read_mostly; | |||
| 43 | 43 | ||
| 44 | static struct percpu_counter nr_files __cacheline_aligned_in_smp; | 44 | static struct percpu_counter nr_files __cacheline_aligned_in_smp; |
| 45 | 45 | ||
| 46 | static inline void file_free_rcu(struct rcu_head *head) | 46 | static void file_free_rcu(struct rcu_head *head) |
| 47 | { | 47 | { |
| 48 | struct file *f = container_of(head, struct file, f_u.fu_rcuhead); | 48 | struct file *f = container_of(head, struct file, f_u.fu_rcuhead); |
| 49 | 49 | ||
| @@ -217,7 +217,7 @@ static void drop_file_write_access(struct file *file) | |||
| 217 | return; | 217 | return; |
| 218 | if (file_check_writeable(file) != 0) | 218 | if (file_check_writeable(file) != 0) |
| 219 | return; | 219 | return; |
| 220 | mnt_drop_write(mnt); | 220 | __mnt_drop_write(mnt); |
| 221 | file_release_write(file); | 221 | file_release_write(file); |
| 222 | } | 222 | } |
| 223 | 223 | ||
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index b321a688cde7..93d8d6c9494d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -944,9 +944,8 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 944 | return err; | 944 | return err; |
| 945 | 945 | ||
| 946 | count = ocount; | 946 | count = ocount; |
| 947 | 947 | sb_start_write(inode->i_sb); | |
| 948 | mutex_lock(&inode->i_mutex); | 948 | mutex_lock(&inode->i_mutex); |
| 949 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
| 950 | 949 | ||
| 951 | /* We can write back this queue in page reclaim */ | 950 | /* We can write back this queue in page reclaim */ |
| 952 | current->backing_dev_info = mapping->backing_dev_info; | 951 | current->backing_dev_info = mapping->backing_dev_info; |
| @@ -1004,6 +1003,7 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 1004 | out: | 1003 | out: |
| 1005 | current->backing_dev_info = NULL; | 1004 | current->backing_dev_info = NULL; |
| 1006 | mutex_unlock(&inode->i_mutex); | 1005 | mutex_unlock(&inode->i_mutex); |
| 1006 | sb_end_write(inode->i_sb); | ||
| 1007 | 1007 | ||
| 1008 | return written ? written : err; | 1008 | return written ? written : err; |
| 1009 | } | 1009 | } |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 9aa6af13823c..d1d791ef38de 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
| @@ -373,11 +373,10 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 373 | loff_t size; | 373 | loff_t size; |
| 374 | int ret; | 374 | int ret; |
| 375 | 375 | ||
| 376 | /* Wait if fs is frozen. This is racy so we check again later on | 376 | sb_start_pagefault(inode->i_sb); |
| 377 | * and retry if the fs has been frozen after the page lock has | 377 | |
| 378 | * been acquired | 378 | /* Update file times before taking page lock */ |
| 379 | */ | 379 | file_update_time(vma->vm_file); |
| 380 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
| 381 | 380 | ||
| 382 | ret = gfs2_rs_alloc(ip); | 381 | ret = gfs2_rs_alloc(ip); |
| 383 | if (ret) | 382 | if (ret) |
| @@ -462,14 +461,9 @@ out: | |||
| 462 | gfs2_holder_uninit(&gh); | 461 | gfs2_holder_uninit(&gh); |
| 463 | if (ret == 0) { | 462 | if (ret == 0) { |
| 464 | set_page_dirty(page); | 463 | set_page_dirty(page); |
| 465 | /* This check must be post dropping of transaction lock */ | 464 | wait_on_page_writeback(page); |
| 466 | if (inode->i_sb->s_frozen == SB_UNFROZEN) { | ||
| 467 | wait_on_page_writeback(page); | ||
| 468 | } else { | ||
| 469 | ret = -EAGAIN; | ||
| 470 | unlock_page(page); | ||
| 471 | } | ||
| 472 | } | 465 | } |
| 466 | sb_end_pagefault(inode->i_sb); | ||
| 473 | return block_page_mkwrite_return(ret); | 467 | return block_page_mkwrite_return(ret); |
| 474 | } | 468 | } |
| 475 | 469 | ||
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index ad3e2fb763d7..adbd27875ef9 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c | |||
| @@ -50,6 +50,7 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, | |||
| 50 | if (revokes) | 50 | if (revokes) |
| 51 | tr->tr_reserved += gfs2_struct2blk(sdp, revokes, | 51 | tr->tr_reserved += gfs2_struct2blk(sdp, revokes, |
| 52 | sizeof(u64)); | 52 | sizeof(u64)); |
| 53 | sb_start_intwrite(sdp->sd_vfs); | ||
| 53 | gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); | 54 | gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); |
| 54 | 55 | ||
| 55 | error = gfs2_glock_nq(&tr->tr_t_gh); | 56 | error = gfs2_glock_nq(&tr->tr_t_gh); |
| @@ -68,6 +69,7 @@ fail_gunlock: | |||
| 68 | gfs2_glock_dq(&tr->tr_t_gh); | 69 | gfs2_glock_dq(&tr->tr_t_gh); |
| 69 | 70 | ||
| 70 | fail_holder_uninit: | 71 | fail_holder_uninit: |
| 72 | sb_end_intwrite(sdp->sd_vfs); | ||
| 71 | gfs2_holder_uninit(&tr->tr_t_gh); | 73 | gfs2_holder_uninit(&tr->tr_t_gh); |
| 72 | kfree(tr); | 74 | kfree(tr); |
| 73 | 75 | ||
| @@ -116,6 +118,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) | |||
| 116 | gfs2_holder_uninit(&tr->tr_t_gh); | 118 | gfs2_holder_uninit(&tr->tr_t_gh); |
| 117 | kfree(tr); | 119 | kfree(tr); |
| 118 | } | 120 | } |
| 121 | sb_end_intwrite(sdp->sd_vfs); | ||
| 119 | return; | 122 | return; |
| 120 | } | 123 | } |
| 121 | 124 | ||
| @@ -136,6 +139,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) | |||
| 136 | 139 | ||
| 137 | if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) | 140 | if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) |
| 138 | gfs2_log_flush(sdp, NULL); | 141 | gfs2_log_flush(sdp, NULL); |
| 142 | sb_end_intwrite(sdp->sd_vfs); | ||
| 139 | } | 143 | } |
| 140 | 144 | ||
| 141 | /** | 145 | /** |
diff --git a/fs/inode.c b/fs/inode.c index 3cc504320467..ac8d904b3f16 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -1542,9 +1542,11 @@ void touch_atime(struct path *path) | |||
| 1542 | if (timespec_equal(&inode->i_atime, &now)) | 1542 | if (timespec_equal(&inode->i_atime, &now)) |
| 1543 | return; | 1543 | return; |
| 1544 | 1544 | ||
| 1545 | if (mnt_want_write(mnt)) | 1545 | if (!sb_start_write_trylock(inode->i_sb)) |
| 1546 | return; | 1546 | return; |
| 1547 | 1547 | ||
| 1548 | if (__mnt_want_write(mnt)) | ||
| 1549 | goto skip_update; | ||
| 1548 | /* | 1550 | /* |
| 1549 | * File systems can error out when updating inodes if they need to | 1551 | * File systems can error out when updating inodes if they need to |
| 1550 | * allocate new space to modify an inode (such is the case for | 1552 | * allocate new space to modify an inode (such is the case for |
| @@ -1555,7 +1557,9 @@ void touch_atime(struct path *path) | |||
| 1555 | * of the fs read only, e.g. subvolumes in Btrfs. | 1557 | * of the fs read only, e.g. subvolumes in Btrfs. |
| 1556 | */ | 1558 | */ |
| 1557 | update_time(inode, &now, S_ATIME); | 1559 | update_time(inode, &now, S_ATIME); |
| 1558 | mnt_drop_write(mnt); | 1560 | __mnt_drop_write(mnt); |
| 1561 | skip_update: | ||
| 1562 | sb_end_write(inode->i_sb); | ||
| 1559 | } | 1563 | } |
| 1560 | EXPORT_SYMBOL(touch_atime); | 1564 | EXPORT_SYMBOL(touch_atime); |
| 1561 | 1565 | ||
| @@ -1662,11 +1666,11 @@ int file_update_time(struct file *file) | |||
| 1662 | return 0; | 1666 | return 0; |
| 1663 | 1667 | ||
| 1664 | /* Finally allowed to write? Takes lock. */ | 1668 | /* Finally allowed to write? Takes lock. */ |
| 1665 | if (mnt_want_write_file(file)) | 1669 | if (__mnt_want_write_file(file)) |
| 1666 | return 0; | 1670 | return 0; |
| 1667 | 1671 | ||
| 1668 | ret = update_time(inode, &now, sync_it); | 1672 | ret = update_time(inode, &now, sync_it); |
| 1669 | mnt_drop_write_file(file); | 1673 | __mnt_drop_write_file(file); |
| 1670 | 1674 | ||
| 1671 | return ret; | 1675 | return ret; |
| 1672 | } | 1676 | } |
diff --git a/fs/internal.h b/fs/internal.h index a6fd56c68b11..371bcc4b1697 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
| @@ -61,6 +61,10 @@ extern void __init mnt_init(void); | |||
| 61 | 61 | ||
| 62 | extern struct lglock vfsmount_lock; | 62 | extern struct lglock vfsmount_lock; |
| 63 | 63 | ||
| 64 | extern int __mnt_want_write(struct vfsmount *); | ||
| 65 | extern int __mnt_want_write_file(struct file *); | ||
| 66 | extern void __mnt_drop_write(struct vfsmount *); | ||
| 67 | extern void __mnt_drop_write_file(struct file *); | ||
| 64 | 68 | ||
| 65 | /* | 69 | /* |
| 66 | * fs_struct.c | 70 | * fs_struct.c |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 8392cb85bd54..05d29124c6ab 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
| @@ -156,12 +156,16 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl) | |||
| 156 | struct nlm_rqst *call; | 156 | struct nlm_rqst *call; |
| 157 | int status; | 157 | int status; |
| 158 | 158 | ||
| 159 | nlm_get_host(host); | ||
| 160 | call = nlm_alloc_call(host); | 159 | call = nlm_alloc_call(host); |
| 161 | if (call == NULL) | 160 | if (call == NULL) |
| 162 | return -ENOMEM; | 161 | return -ENOMEM; |
| 163 | 162 | ||
| 164 | nlmclnt_locks_init_private(fl, host); | 163 | nlmclnt_locks_init_private(fl, host); |
| 164 | if (!fl->fl_u.nfs_fl.owner) { | ||
| 165 | /* lockowner allocation has failed */ | ||
| 166 | nlmclnt_release_call(call); | ||
| 167 | return -ENOMEM; | ||
| 168 | } | ||
| 165 | /* Set up the argument struct */ | 169 | /* Set up the argument struct */ |
| 166 | nlmclnt_setlockargs(call, fl); | 170 | nlmclnt_setlockargs(call, fl); |
| 167 | 171 | ||
| @@ -185,9 +189,6 @@ EXPORT_SYMBOL_GPL(nlmclnt_proc); | |||
| 185 | 189 | ||
| 186 | /* | 190 | /* |
| 187 | * Allocate an NLM RPC call struct | 191 | * Allocate an NLM RPC call struct |
| 188 | * | ||
| 189 | * Note: the caller must hold a reference to host. In case of failure, | ||
| 190 | * this reference will be released. | ||
| 191 | */ | 192 | */ |
| 192 | struct nlm_rqst *nlm_alloc_call(struct nlm_host *host) | 193 | struct nlm_rqst *nlm_alloc_call(struct nlm_host *host) |
| 193 | { | 194 | { |
| @@ -199,7 +200,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host) | |||
| 199 | atomic_set(&call->a_count, 1); | 200 | atomic_set(&call->a_count, 1); |
| 200 | locks_init_lock(&call->a_args.lock.fl); | 201 | locks_init_lock(&call->a_args.lock.fl); |
| 201 | locks_init_lock(&call->a_res.lock.fl); | 202 | locks_init_lock(&call->a_res.lock.fl); |
| 202 | call->a_host = host; | 203 | call->a_host = nlm_get_host(host); |
| 203 | return call; | 204 | return call; |
| 204 | } | 205 | } |
| 205 | if (signalled()) | 206 | if (signalled()) |
| @@ -207,7 +208,6 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host) | |||
| 207 | printk("nlm_alloc_call: failed, waiting for memory\n"); | 208 | printk("nlm_alloc_call: failed, waiting for memory\n"); |
| 208 | schedule_timeout_interruptible(5*HZ); | 209 | schedule_timeout_interruptible(5*HZ); |
| 209 | } | 210 | } |
| 210 | nlmclnt_release_host(host); | ||
| 211 | return NULL; | 211 | return NULL; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| @@ -750,7 +750,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl | |||
| 750 | dprintk("lockd: blocking lock attempt was interrupted by a signal.\n" | 750 | dprintk("lockd: blocking lock attempt was interrupted by a signal.\n" |
| 751 | " Attempting to cancel lock.\n"); | 751 | " Attempting to cancel lock.\n"); |
| 752 | 752 | ||
| 753 | req = nlm_alloc_call(nlm_get_host(host)); | 753 | req = nlm_alloc_call(host); |
| 754 | if (!req) | 754 | if (!req) |
| 755 | return -ENOMEM; | 755 | return -ENOMEM; |
| 756 | req->a_flags = RPC_TASK_ASYNC; | 756 | req->a_flags = RPC_TASK_ASYNC; |
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 4a43d253c045..b147d1ae71fd 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
| @@ -257,6 +257,7 @@ static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args | |||
| 257 | return rpc_system_err; | 257 | return rpc_system_err; |
| 258 | 258 | ||
| 259 | call = nlm_alloc_call(host); | 259 | call = nlm_alloc_call(host); |
| 260 | nlmsvc_release_host(host); | ||
| 260 | if (call == NULL) | 261 | if (call == NULL) |
| 261 | return rpc_system_err; | 262 | return rpc_system_err; |
| 262 | 263 | ||
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index afe4488c33d8..fb1a2bedbe97 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
| @@ -219,7 +219,6 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host, | |||
| 219 | struct nlm_block *block; | 219 | struct nlm_block *block; |
| 220 | struct nlm_rqst *call = NULL; | 220 | struct nlm_rqst *call = NULL; |
| 221 | 221 | ||
| 222 | nlm_get_host(host); | ||
| 223 | call = nlm_alloc_call(host); | 222 | call = nlm_alloc_call(host); |
| 224 | if (call == NULL) | 223 | if (call == NULL) |
| 225 | return NULL; | 224 | return NULL; |
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index de8f2caa2235..3009a365e082 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
| @@ -297,6 +297,7 @@ static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args | |||
| 297 | return rpc_system_err; | 297 | return rpc_system_err; |
| 298 | 298 | ||
| 299 | call = nlm_alloc_call(host); | 299 | call = nlm_alloc_call(host); |
| 300 | nlmsvc_release_host(host); | ||
| 300 | if (call == NULL) | 301 | if (call == NULL) |
| 301 | return rpc_system_err; | 302 | return rpc_system_err; |
| 302 | 303 | ||
diff --git a/fs/namei.c b/fs/namei.c index 2ccc35c4dc24..1b464390dde8 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -650,6 +650,121 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki | |||
| 650 | path_put(link); | 650 | path_put(link); |
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | int sysctl_protected_symlinks __read_mostly = 1; | ||
| 654 | int sysctl_protected_hardlinks __read_mostly = 1; | ||
| 655 | |||
| 656 | /** | ||
| 657 | * may_follow_link - Check symlink following for unsafe situations | ||
| 658 | * @link: The path of the symlink | ||
| 659 | * | ||
| 660 | * In the case of the sysctl_protected_symlinks sysctl being enabled, | ||
| 661 | * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is | ||
| 662 | * in a sticky world-writable directory. This is to protect privileged | ||
| 663 | * processes from failing races against path names that may change out | ||
| 664 | * from under them by way of other users creating malicious symlinks. | ||
| 665 | * It will permit symlinks to be followed only when outside a sticky | ||
| 666 | * world-writable directory, or when the uid of the symlink and follower | ||
| 667 | * match, or when the directory owner matches the symlink's owner. | ||
| 668 | * | ||
| 669 | * Returns 0 if following the symlink is allowed, -ve on error. | ||
| 670 | */ | ||
| 671 | static inline int may_follow_link(struct path *link, struct nameidata *nd) | ||
| 672 | { | ||
| 673 | const struct inode *inode; | ||
| 674 | const struct inode *parent; | ||
| 675 | |||
| 676 | if (!sysctl_protected_symlinks) | ||
| 677 | return 0; | ||
| 678 | |||
| 679 | /* Allowed if owner and follower match. */ | ||
| 680 | inode = link->dentry->d_inode; | ||
| 681 | if (current_cred()->fsuid == inode->i_uid) | ||
| 682 | return 0; | ||
| 683 | |||
| 684 | /* Allowed if parent directory not sticky and world-writable. */ | ||
| 685 | parent = nd->path.dentry->d_inode; | ||
| 686 | if ((parent->i_mode & (S_ISVTX|S_IWOTH)) != (S_ISVTX|S_IWOTH)) | ||
| 687 | return 0; | ||
| 688 | |||
| 689 | /* Allowed if parent directory and link owner match. */ | ||
| 690 | if (parent->i_uid == inode->i_uid) | ||
| 691 | return 0; | ||
| 692 | |||
| 693 | path_put_conditional(link, nd); | ||
| 694 | path_put(&nd->path); | ||
| 695 | audit_log_link_denied("follow_link", link); | ||
| 696 | return -EACCES; | ||
| 697 | } | ||
| 698 | |||
| 699 | /** | ||
| 700 | * safe_hardlink_source - Check for safe hardlink conditions | ||
| 701 | * @inode: the source inode to hardlink from | ||
| 702 | * | ||
| 703 | * Return false if at least one of the following conditions: | ||
| 704 | * - inode is not a regular file | ||
| 705 | * - inode is setuid | ||
| 706 | * - inode is setgid and group-exec | ||
| 707 | * - access failure for read and write | ||
| 708 | * | ||
| 709 | * Otherwise returns true. | ||
| 710 | */ | ||
| 711 | static bool safe_hardlink_source(struct inode *inode) | ||
| 712 | { | ||
| 713 | umode_t mode = inode->i_mode; | ||
| 714 | |||
| 715 | /* Special files should not get pinned to the filesystem. */ | ||
| 716 | if (!S_ISREG(mode)) | ||
| 717 | return false; | ||
| 718 | |||
| 719 | /* Setuid files should not get pinned to the filesystem. */ | ||
| 720 | if (mode & S_ISUID) | ||
| 721 | return false; | ||
| 722 | |||
| 723 | /* Executable setgid files should not get pinned to the filesystem. */ | ||
| 724 | if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) | ||
| 725 | return false; | ||
| 726 | |||
| 727 | /* Hardlinking to unreadable or unwritable sources is dangerous. */ | ||
| 728 | if (inode_permission(inode, MAY_READ | MAY_WRITE)) | ||
| 729 | return false; | ||
| 730 | |||
| 731 | return true; | ||
| 732 | } | ||
| 733 | |||
| 734 | /** | ||
| 735 | * may_linkat - Check permissions for creating a hardlink | ||
| 736 | * @link: the source to hardlink from | ||
| 737 | * | ||
| 738 | * Block hardlink when all of: | ||
| 739 | * - sysctl_protected_hardlinks enabled | ||
| 740 | * - fsuid does not match inode | ||
| 741 | * - hardlink source is unsafe (see safe_hardlink_source() above) | ||
| 742 | * - not CAP_FOWNER | ||
| 743 | * | ||
| 744 | * Returns 0 if successful, -ve on error. | ||
| 745 | */ | ||
| 746 | static int may_linkat(struct path *link) | ||
| 747 | { | ||
| 748 | const struct cred *cred; | ||
| 749 | struct inode *inode; | ||
| 750 | |||
| 751 | if (!sysctl_protected_hardlinks) | ||
| 752 | return 0; | ||
| 753 | |||
| 754 | cred = current_cred(); | ||
| 755 | inode = link->dentry->d_inode; | ||
| 756 | |||
| 757 | /* Source inode owner (or CAP_FOWNER) can hardlink all they like, | ||
| 758 | * otherwise, it must be a safe source. | ||
| 759 | */ | ||
| 760 | if (cred->fsuid == inode->i_uid || safe_hardlink_source(inode) || | ||
| 761 | capable(CAP_FOWNER)) | ||
| 762 | return 0; | ||
| 763 | |||
| 764 | audit_log_link_denied("linkat", link); | ||
| 765 | return -EPERM; | ||
| 766 | } | ||
| 767 | |||
| 653 | static __always_inline int | 768 | static __always_inline int |
| 654 | follow_link(struct path *link, struct nameidata *nd, void **p) | 769 | follow_link(struct path *link, struct nameidata *nd, void **p) |
| 655 | { | 770 | { |
| @@ -1818,6 +1933,9 @@ static int path_lookupat(int dfd, const char *name, | |||
| 1818 | while (err > 0) { | 1933 | while (err > 0) { |
| 1819 | void *cookie; | 1934 | void *cookie; |
| 1820 | struct path link = path; | 1935 | struct path link = path; |
| 1936 | err = may_follow_link(&link, nd); | ||
| 1937 | if (unlikely(err)) | ||
| 1938 | break; | ||
| 1821 | nd->flags |= LOOKUP_PARENT; | 1939 | nd->flags |= LOOKUP_PARENT; |
| 1822 | err = follow_link(&link, nd, &cookie); | 1940 | err = follow_link(&link, nd, &cookie); |
| 1823 | if (err) | 1941 | if (err) |
| @@ -2277,7 +2395,7 @@ static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode) | |||
| 2277 | static int atomic_open(struct nameidata *nd, struct dentry *dentry, | 2395 | static int atomic_open(struct nameidata *nd, struct dentry *dentry, |
| 2278 | struct path *path, struct file *file, | 2396 | struct path *path, struct file *file, |
| 2279 | const struct open_flags *op, | 2397 | const struct open_flags *op, |
| 2280 | bool *want_write, bool need_lookup, | 2398 | bool got_write, bool need_lookup, |
| 2281 | int *opened) | 2399 | int *opened) |
| 2282 | { | 2400 | { |
| 2283 | struct inode *dir = nd->path.dentry->d_inode; | 2401 | struct inode *dir = nd->path.dentry->d_inode; |
| @@ -2300,7 +2418,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
| 2300 | if ((open_flag & O_CREAT) && !IS_POSIXACL(dir)) | 2418 | if ((open_flag & O_CREAT) && !IS_POSIXACL(dir)) |
| 2301 | mode &= ~current_umask(); | 2419 | mode &= ~current_umask(); |
| 2302 | 2420 | ||
| 2303 | if (open_flag & O_EXCL) { | 2421 | if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) { |
| 2304 | open_flag &= ~O_TRUNC; | 2422 | open_flag &= ~O_TRUNC; |
| 2305 | *opened |= FILE_CREATED; | 2423 | *opened |= FILE_CREATED; |
| 2306 | } | 2424 | } |
| @@ -2314,12 +2432,9 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
| 2314 | * Another problem is returing the "right" error value (e.g. for an | 2432 | * Another problem is returing the "right" error value (e.g. for an |
| 2315 | * O_EXCL open we want to return EEXIST not EROFS). | 2433 | * O_EXCL open we want to return EEXIST not EROFS). |
| 2316 | */ | 2434 | */ |
| 2317 | if ((open_flag & (O_CREAT | O_TRUNC)) || | 2435 | if (((open_flag & (O_CREAT | O_TRUNC)) || |
| 2318 | (open_flag & O_ACCMODE) != O_RDONLY) { | 2436 | (open_flag & O_ACCMODE) != O_RDONLY) && unlikely(!got_write)) { |
| 2319 | error = mnt_want_write(nd->path.mnt); | 2437 | if (!(open_flag & O_CREAT)) { |
| 2320 | if (!error) { | ||
| 2321 | *want_write = true; | ||
| 2322 | } else if (!(open_flag & O_CREAT)) { | ||
| 2323 | /* | 2438 | /* |
| 2324 | * No O_CREATE -> atomicity not a requirement -> fall | 2439 | * No O_CREATE -> atomicity not a requirement -> fall |
| 2325 | * back to lookup + open | 2440 | * back to lookup + open |
| @@ -2327,11 +2442,11 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
| 2327 | goto no_open; | 2442 | goto no_open; |
| 2328 | } else if (open_flag & (O_EXCL | O_TRUNC)) { | 2443 | } else if (open_flag & (O_EXCL | O_TRUNC)) { |
| 2329 | /* Fall back and fail with the right error */ | 2444 | /* Fall back and fail with the right error */ |
| 2330 | create_error = error; | 2445 | create_error = -EROFS; |
| 2331 | goto no_open; | 2446 | goto no_open; |
| 2332 | } else { | 2447 | } else { |
| 2333 | /* No side effects, safe to clear O_CREAT */ | 2448 | /* No side effects, safe to clear O_CREAT */ |
| 2334 | create_error = error; | 2449 | create_error = -EROFS; |
| 2335 | open_flag &= ~O_CREAT; | 2450 | open_flag &= ~O_CREAT; |
| 2336 | } | 2451 | } |
| 2337 | } | 2452 | } |
| @@ -2438,7 +2553,7 @@ looked_up: | |||
| 2438 | static int lookup_open(struct nameidata *nd, struct path *path, | 2553 | static int lookup_open(struct nameidata *nd, struct path *path, |
| 2439 | struct file *file, | 2554 | struct file *file, |
| 2440 | const struct open_flags *op, | 2555 | const struct open_flags *op, |
| 2441 | bool *want_write, int *opened) | 2556 | bool got_write, int *opened) |
| 2442 | { | 2557 | { |
| 2443 | struct dentry *dir = nd->path.dentry; | 2558 | struct dentry *dir = nd->path.dentry; |
| 2444 | struct inode *dir_inode = dir->d_inode; | 2559 | struct inode *dir_inode = dir->d_inode; |
| @@ -2456,7 +2571,7 @@ static int lookup_open(struct nameidata *nd, struct path *path, | |||
| 2456 | goto out_no_open; | 2571 | goto out_no_open; |
| 2457 | 2572 | ||
| 2458 | if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) { | 2573 | if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) { |
| 2459 | return atomic_open(nd, dentry, path, file, op, want_write, | 2574 | return atomic_open(nd, dentry, path, file, op, got_write, |
| 2460 | need_lookup, opened); | 2575 | need_lookup, opened); |
| 2461 | } | 2576 | } |
| 2462 | 2577 | ||
| @@ -2480,10 +2595,10 @@ static int lookup_open(struct nameidata *nd, struct path *path, | |||
| 2480 | * a permanent write count is taken through | 2595 | * a permanent write count is taken through |
| 2481 | * the 'struct file' in finish_open(). | 2596 | * the 'struct file' in finish_open(). |
| 2482 | */ | 2597 | */ |
| 2483 | error = mnt_want_write(nd->path.mnt); | 2598 | if (!got_write) { |
| 2484 | if (error) | 2599 | error = -EROFS; |
| 2485 | goto out_dput; | 2600 | goto out_dput; |
| 2486 | *want_write = true; | 2601 | } |
| 2487 | *opened |= FILE_CREATED; | 2602 | *opened |= FILE_CREATED; |
| 2488 | error = security_path_mknod(&nd->path, dentry, mode, 0); | 2603 | error = security_path_mknod(&nd->path, dentry, mode, 0); |
| 2489 | if (error) | 2604 | if (error) |
| @@ -2513,7 +2628,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
| 2513 | struct dentry *dir = nd->path.dentry; | 2628 | struct dentry *dir = nd->path.dentry; |
| 2514 | int open_flag = op->open_flag; | 2629 | int open_flag = op->open_flag; |
| 2515 | bool will_truncate = (open_flag & O_TRUNC) != 0; | 2630 | bool will_truncate = (open_flag & O_TRUNC) != 0; |
| 2516 | bool want_write = false; | 2631 | bool got_write = false; |
| 2517 | int acc_mode = op->acc_mode; | 2632 | int acc_mode = op->acc_mode; |
| 2518 | struct inode *inode; | 2633 | struct inode *inode; |
| 2519 | bool symlink_ok = false; | 2634 | bool symlink_ok = false; |
| @@ -2582,8 +2697,18 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
| 2582 | } | 2697 | } |
| 2583 | 2698 | ||
| 2584 | retry_lookup: | 2699 | retry_lookup: |
| 2700 | if (op->open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) { | ||
| 2701 | error = mnt_want_write(nd->path.mnt); | ||
| 2702 | if (!error) | ||
| 2703 | got_write = true; | ||
| 2704 | /* | ||
| 2705 | * do _not_ fail yet - we might not need that or fail with | ||
| 2706 | * a different error; let lookup_open() decide; we'll be | ||
| 2707 | * dropping this one anyway. | ||
| 2708 | */ | ||
| 2709 | } | ||
| 2585 | mutex_lock(&dir->d_inode->i_mutex); | 2710 | mutex_lock(&dir->d_inode->i_mutex); |
| 2586 | error = lookup_open(nd, path, file, op, &want_write, opened); | 2711 | error = lookup_open(nd, path, file, op, got_write, opened); |
| 2587 | mutex_unlock(&dir->d_inode->i_mutex); | 2712 | mutex_unlock(&dir->d_inode->i_mutex); |
| 2588 | 2713 | ||
| 2589 | if (error <= 0) { | 2714 | if (error <= 0) { |
| @@ -2608,22 +2733,23 @@ retry_lookup: | |||
| 2608 | } | 2733 | } |
| 2609 | 2734 | ||
| 2610 | /* | 2735 | /* |
| 2611 | * It already exists. | 2736 | * create/update audit record if it already exists. |
| 2612 | */ | 2737 | */ |
| 2613 | audit_inode(pathname, path->dentry); | 2738 | if (path->dentry->d_inode) |
| 2739 | audit_inode(pathname, path->dentry); | ||
| 2614 | 2740 | ||
| 2615 | /* | 2741 | /* |
| 2616 | * If atomic_open() acquired write access it is dropped now due to | 2742 | * If atomic_open() acquired write access it is dropped now due to |
| 2617 | * possible mount and symlink following (this might be optimized away if | 2743 | * possible mount and symlink following (this might be optimized away if |
| 2618 | * necessary...) | 2744 | * necessary...) |
| 2619 | */ | 2745 | */ |
| 2620 | if (want_write) { | 2746 | if (got_write) { |
| 2621 | mnt_drop_write(nd->path.mnt); | 2747 | mnt_drop_write(nd->path.mnt); |
| 2622 | want_write = false; | 2748 | got_write = false; |
| 2623 | } | 2749 | } |
| 2624 | 2750 | ||
| 2625 | error = -EEXIST; | 2751 | error = -EEXIST; |
| 2626 | if (open_flag & O_EXCL) | 2752 | if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) |
| 2627 | goto exit_dput; | 2753 | goto exit_dput; |
| 2628 | 2754 | ||
| 2629 | error = follow_managed(path, nd->flags); | 2755 | error = follow_managed(path, nd->flags); |
| @@ -2684,7 +2810,7 @@ finish_open: | |||
| 2684 | error = mnt_want_write(nd->path.mnt); | 2810 | error = mnt_want_write(nd->path.mnt); |
| 2685 | if (error) | 2811 | if (error) |
| 2686 | goto out; | 2812 | goto out; |
| 2687 | want_write = true; | 2813 | got_write = true; |
| 2688 | } | 2814 | } |
| 2689 | finish_open_created: | 2815 | finish_open_created: |
| 2690 | error = may_open(&nd->path, acc_mode, open_flag); | 2816 | error = may_open(&nd->path, acc_mode, open_flag); |
| @@ -2711,7 +2837,7 @@ opened: | |||
| 2711 | goto exit_fput; | 2837 | goto exit_fput; |
| 2712 | } | 2838 | } |
| 2713 | out: | 2839 | out: |
| 2714 | if (want_write) | 2840 | if (got_write) |
| 2715 | mnt_drop_write(nd->path.mnt); | 2841 | mnt_drop_write(nd->path.mnt); |
| 2716 | path_put(&save_parent); | 2842 | path_put(&save_parent); |
| 2717 | terminate_walk(nd); | 2843 | terminate_walk(nd); |
| @@ -2735,9 +2861,9 @@ stale_open: | |||
| 2735 | nd->inode = dir->d_inode; | 2861 | nd->inode = dir->d_inode; |
| 2736 | save_parent.mnt = NULL; | 2862 | save_parent.mnt = NULL; |
| 2737 | save_parent.dentry = NULL; | 2863 | save_parent.dentry = NULL; |
| 2738 | if (want_write) { | 2864 | if (got_write) { |
| 2739 | mnt_drop_write(nd->path.mnt); | 2865 | mnt_drop_write(nd->path.mnt); |
| 2740 | want_write = false; | 2866 | got_write = false; |
| 2741 | } | 2867 | } |
| 2742 | retried = true; | 2868 | retried = true; |
| 2743 | goto retry_lookup; | 2869 | goto retry_lookup; |
| @@ -2777,6 +2903,9 @@ static struct file *path_openat(int dfd, const char *pathname, | |||
| 2777 | error = -ELOOP; | 2903 | error = -ELOOP; |
| 2778 | break; | 2904 | break; |
| 2779 | } | 2905 | } |
| 2906 | error = may_follow_link(&link, nd); | ||
| 2907 | if (unlikely(error)) | ||
| 2908 | break; | ||
| 2780 | nd->flags |= LOOKUP_PARENT; | 2909 | nd->flags |= LOOKUP_PARENT; |
| 2781 | nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); | 2910 | nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); |
| 2782 | error = follow_link(&link, nd, &cookie); | 2911 | error = follow_link(&link, nd, &cookie); |
| @@ -2846,6 +2975,7 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path | |||
| 2846 | { | 2975 | { |
| 2847 | struct dentry *dentry = ERR_PTR(-EEXIST); | 2976 | struct dentry *dentry = ERR_PTR(-EEXIST); |
| 2848 | struct nameidata nd; | 2977 | struct nameidata nd; |
| 2978 | int err2; | ||
| 2849 | int error = do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd); | 2979 | int error = do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd); |
| 2850 | if (error) | 2980 | if (error) |
| 2851 | return ERR_PTR(error); | 2981 | return ERR_PTR(error); |
| @@ -2859,16 +2989,19 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path | |||
| 2859 | nd.flags &= ~LOOKUP_PARENT; | 2989 | nd.flags &= ~LOOKUP_PARENT; |
| 2860 | nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL; | 2990 | nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL; |
| 2861 | 2991 | ||
| 2992 | /* don't fail immediately if it's r/o, at least try to report other errors */ | ||
| 2993 | err2 = mnt_want_write(nd.path.mnt); | ||
| 2862 | /* | 2994 | /* |
| 2863 | * Do the final lookup. | 2995 | * Do the final lookup. |
| 2864 | */ | 2996 | */ |
| 2865 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 2997 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
| 2866 | dentry = lookup_hash(&nd); | 2998 | dentry = lookup_hash(&nd); |
| 2867 | if (IS_ERR(dentry)) | 2999 | if (IS_ERR(dentry)) |
| 2868 | goto fail; | 3000 | goto unlock; |
| 2869 | 3001 | ||
| 3002 | error = -EEXIST; | ||
| 2870 | if (dentry->d_inode) | 3003 | if (dentry->d_inode) |
| 2871 | goto eexist; | 3004 | goto fail; |
| 2872 | /* | 3005 | /* |
| 2873 | * Special case - lookup gave negative, but... we had foo/bar/ | 3006 | * Special case - lookup gave negative, but... we had foo/bar/ |
| 2874 | * From the vfs_mknod() POV we just have a negative dentry - | 3007 | * From the vfs_mknod() POV we just have a negative dentry - |
| @@ -2876,23 +3009,37 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path | |||
| 2876 | * been asking for (non-existent) directory. -ENOENT for you. | 3009 | * been asking for (non-existent) directory. -ENOENT for you. |
| 2877 | */ | 3010 | */ |
| 2878 | if (unlikely(!is_dir && nd.last.name[nd.last.len])) { | 3011 | if (unlikely(!is_dir && nd.last.name[nd.last.len])) { |
| 2879 | dput(dentry); | 3012 | error = -ENOENT; |
| 2880 | dentry = ERR_PTR(-ENOENT); | 3013 | goto fail; |
| 3014 | } | ||
| 3015 | if (unlikely(err2)) { | ||
| 3016 | error = err2; | ||
| 2881 | goto fail; | 3017 | goto fail; |
| 2882 | } | 3018 | } |
| 2883 | *path = nd.path; | 3019 | *path = nd.path; |
| 2884 | return dentry; | 3020 | return dentry; |
| 2885 | eexist: | ||
| 2886 | dput(dentry); | ||
| 2887 | dentry = ERR_PTR(-EEXIST); | ||
| 2888 | fail: | 3021 | fail: |
| 3022 | dput(dentry); | ||
| 3023 | dentry = ERR_PTR(error); | ||
| 3024 | unlock: | ||
| 2889 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 3025 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
| 3026 | if (!err2) | ||
| 3027 | mnt_drop_write(nd.path.mnt); | ||
| 2890 | out: | 3028 | out: |
| 2891 | path_put(&nd.path); | 3029 | path_put(&nd.path); |
| 2892 | return dentry; | 3030 | return dentry; |
| 2893 | } | 3031 | } |
| 2894 | EXPORT_SYMBOL(kern_path_create); | 3032 | EXPORT_SYMBOL(kern_path_create); |
| 2895 | 3033 | ||
| 3034 | void done_path_create(struct path *path, struct dentry *dentry) | ||
| 3035 | { | ||
| 3036 | dput(dentry); | ||
| 3037 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
| 3038 | mnt_drop_write(path->mnt); | ||
| 3039 | path_put(path); | ||
| 3040 | } | ||
| 3041 | EXPORT_SYMBOL(done_path_create); | ||
| 3042 | |||
| 2896 | struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) | 3043 | struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) |
| 2897 | { | 3044 | { |
| 2898 | char *tmp = getname(pathname); | 3045 | char *tmp = getname(pathname); |
| @@ -2956,8 +3103,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, | |||
| 2956 | struct path path; | 3103 | struct path path; |
| 2957 | int error; | 3104 | int error; |
| 2958 | 3105 | ||
| 2959 | if (S_ISDIR(mode)) | 3106 | error = may_mknod(mode); |
| 2960 | return -EPERM; | 3107 | if (error) |
| 3108 | return error; | ||
| 2961 | 3109 | ||
| 2962 | dentry = user_path_create(dfd, filename, &path, 0); | 3110 | dentry = user_path_create(dfd, filename, &path, 0); |
| 2963 | if (IS_ERR(dentry)) | 3111 | if (IS_ERR(dentry)) |
| @@ -2965,15 +3113,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, | |||
| 2965 | 3113 | ||
| 2966 | if (!IS_POSIXACL(path.dentry->d_inode)) | 3114 | if (!IS_POSIXACL(path.dentry->d_inode)) |
| 2967 | mode &= ~current_umask(); | 3115 | mode &= ~current_umask(); |
| 2968 | error = may_mknod(mode); | ||
| 2969 | if (error) | ||
| 2970 | goto out_dput; | ||
| 2971 | error = mnt_want_write(path.mnt); | ||
| 2972 | if (error) | ||
| 2973 | goto out_dput; | ||
| 2974 | error = security_path_mknod(&path, dentry, mode, dev); | 3116 | error = security_path_mknod(&path, dentry, mode, dev); |
| 2975 | if (error) | 3117 | if (error) |
| 2976 | goto out_drop_write; | 3118 | goto out; |
| 2977 | switch (mode & S_IFMT) { | 3119 | switch (mode & S_IFMT) { |
| 2978 | case 0: case S_IFREG: | 3120 | case 0: case S_IFREG: |
| 2979 | error = vfs_create(path.dentry->d_inode,dentry,mode,true); | 3121 | error = vfs_create(path.dentry->d_inode,dentry,mode,true); |
| @@ -2986,13 +3128,8 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, | |||
| 2986 | error = vfs_mknod(path.dentry->d_inode,dentry,mode,0); | 3128 | error = vfs_mknod(path.dentry->d_inode,dentry,mode,0); |
| 2987 | break; | 3129 | break; |
| 2988 | } | 3130 | } |
| 2989 | out_drop_write: | 3131 | out: |
| 2990 | mnt_drop_write(path.mnt); | 3132 | done_path_create(&path, dentry); |
| 2991 | out_dput: | ||
| 2992 | dput(dentry); | ||
| 2993 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
| 2994 | path_put(&path); | ||
| 2995 | |||
| 2996 | return error; | 3133 | return error; |
| 2997 | } | 3134 | } |
| 2998 | 3135 | ||
| @@ -3038,19 +3175,10 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode) | |||
| 3038 | 3175 | ||
| 3039 | if (!IS_POSIXACL(path.dentry->d_inode)) | 3176 | if (!IS_POSIXACL(path.dentry->d_inode)) |
| 3040 | mode &= ~current_umask(); | 3177 | mode &= ~current_umask(); |
| 3041 | error = mnt_want_write(path.mnt); | ||
| 3042 | if (error) | ||
| 3043 | goto out_dput; | ||
| 3044 | error = security_path_mkdir(&path, dentry, mode); | 3178 | error = security_path_mkdir(&path, dentry, mode); |
| 3045 | if (error) | 3179 | if (!error) |
| 3046 | goto out_drop_write; | 3180 | error = vfs_mkdir(path.dentry->d_inode, dentry, mode); |
| 3047 | error = vfs_mkdir(path.dentry->d_inode, dentry, mode); | 3181 | done_path_create(&path, dentry); |
| 3048 | out_drop_write: | ||
| 3049 | mnt_drop_write(path.mnt); | ||
| 3050 | out_dput: | ||
| 3051 | dput(dentry); | ||
| 3052 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
| 3053 | path_put(&path); | ||
| 3054 | return error; | 3182 | return error; |
| 3055 | } | 3183 | } |
| 3056 | 3184 | ||
| @@ -3144,6 +3272,9 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
| 3144 | } | 3272 | } |
| 3145 | 3273 | ||
| 3146 | nd.flags &= ~LOOKUP_PARENT; | 3274 | nd.flags &= ~LOOKUP_PARENT; |
| 3275 | error = mnt_want_write(nd.path.mnt); | ||
| 3276 | if (error) | ||
| 3277 | goto exit1; | ||
| 3147 | 3278 | ||
| 3148 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 3279 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
| 3149 | dentry = lookup_hash(&nd); | 3280 | dentry = lookup_hash(&nd); |
| @@ -3154,19 +3285,15 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
| 3154 | error = -ENOENT; | 3285 | error = -ENOENT; |
| 3155 | goto exit3; | 3286 | goto exit3; |
| 3156 | } | 3287 | } |
| 3157 | error = mnt_want_write(nd.path.mnt); | ||
| 3158 | if (error) | ||
| 3159 | goto exit3; | ||
| 3160 | error = security_path_rmdir(&nd.path, dentry); | 3288 | error = security_path_rmdir(&nd.path, dentry); |
| 3161 | if (error) | 3289 | if (error) |
| 3162 | goto exit4; | 3290 | goto exit3; |
| 3163 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 3291 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
| 3164 | exit4: | ||
| 3165 | mnt_drop_write(nd.path.mnt); | ||
| 3166 | exit3: | 3292 | exit3: |
| 3167 | dput(dentry); | 3293 | dput(dentry); |
| 3168 | exit2: | 3294 | exit2: |
| 3169 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 3295 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
| 3296 | mnt_drop_write(nd.path.mnt); | ||
| 3170 | exit1: | 3297 | exit1: |
| 3171 | path_put(&nd.path); | 3298 | path_put(&nd.path); |
| 3172 | putname(name); | 3299 | putname(name); |
| @@ -3233,6 +3360,9 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
| 3233 | goto exit1; | 3360 | goto exit1; |
| 3234 | 3361 | ||
| 3235 | nd.flags &= ~LOOKUP_PARENT; | 3362 | nd.flags &= ~LOOKUP_PARENT; |
| 3363 | error = mnt_want_write(nd.path.mnt); | ||
| 3364 | if (error) | ||
| 3365 | goto exit1; | ||
| 3236 | 3366 | ||
| 3237 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 3367 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
| 3238 | dentry = lookup_hash(&nd); | 3368 | dentry = lookup_hash(&nd); |
| @@ -3245,21 +3375,17 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
| 3245 | if (!inode) | 3375 | if (!inode) |
| 3246 | goto slashes; | 3376 | goto slashes; |
| 3247 | ihold(inode); | 3377 | ihold(inode); |
| 3248 | error = mnt_want_write(nd.path.mnt); | ||
| 3249 | if (error) | ||
| 3250 | goto exit2; | ||
| 3251 | error = security_path_unlink(&nd.path, dentry); | 3378 | error = security_path_unlink(&nd.path, dentry); |
| 3252 | if (error) | 3379 | if (error) |
| 3253 | goto exit3; | 3380 | goto exit2; |
| 3254 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 3381 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
| 3255 | exit3: | 3382 | exit2: |
| 3256 | mnt_drop_write(nd.path.mnt); | ||
| 3257 | exit2: | ||
| 3258 | dput(dentry); | 3383 | dput(dentry); |
| 3259 | } | 3384 | } |
| 3260 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 3385 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
| 3261 | if (inode) | 3386 | if (inode) |
| 3262 | iput(inode); /* truncate the inode here */ | 3387 | iput(inode); /* truncate the inode here */ |
| 3388 | mnt_drop_write(nd.path.mnt); | ||
| 3263 | exit1: | 3389 | exit1: |
| 3264 | path_put(&nd.path); | 3390 | path_put(&nd.path); |
| 3265 | putname(name); | 3391 | putname(name); |
| @@ -3324,19 +3450,10 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, | |||
| 3324 | if (IS_ERR(dentry)) | 3450 | if (IS_ERR(dentry)) |
| 3325 | goto out_putname; | 3451 | goto out_putname; |
| 3326 | 3452 | ||
| 3327 | error = mnt_want_write(path.mnt); | ||
| 3328 | if (error) | ||
| 3329 | goto out_dput; | ||
| 3330 | error = security_path_symlink(&path, dentry, from); | 3453 | error = security_path_symlink(&path, dentry, from); |
| 3331 | if (error) | 3454 | if (!error) |
| 3332 | goto out_drop_write; | 3455 | error = vfs_symlink(path.dentry->d_inode, dentry, from); |
| 3333 | error = vfs_symlink(path.dentry->d_inode, dentry, from); | 3456 | done_path_create(&path, dentry); |
| 3334 | out_drop_write: | ||
| 3335 | mnt_drop_write(path.mnt); | ||
| 3336 | out_dput: | ||
| 3337 | dput(dentry); | ||
| 3338 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
| 3339 | path_put(&path); | ||
| 3340 | out_putname: | 3457 | out_putname: |
| 3341 | putname(from); | 3458 | putname(from); |
| 3342 | return error; | 3459 | return error; |
| @@ -3436,19 +3553,15 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, | |||
| 3436 | error = -EXDEV; | 3553 | error = -EXDEV; |
| 3437 | if (old_path.mnt != new_path.mnt) | 3554 | if (old_path.mnt != new_path.mnt) |
| 3438 | goto out_dput; | 3555 | goto out_dput; |
| 3439 | error = mnt_want_write(new_path.mnt); | 3556 | error = may_linkat(&old_path); |
| 3440 | if (error) | 3557 | if (unlikely(error)) |
| 3441 | goto out_dput; | 3558 | goto out_dput; |
| 3442 | error = security_path_link(old_path.dentry, &new_path, new_dentry); | 3559 | error = security_path_link(old_path.dentry, &new_path, new_dentry); |
| 3443 | if (error) | 3560 | if (error) |
| 3444 | goto out_drop_write; | 3561 | goto out_dput; |
| 3445 | error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry); | 3562 | error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry); |
| 3446 | out_drop_write: | ||
| 3447 | mnt_drop_write(new_path.mnt); | ||
| 3448 | out_dput: | 3563 | out_dput: |
| 3449 | dput(new_dentry); | 3564 | done_path_create(&new_path, new_dentry); |
| 3450 | mutex_unlock(&new_path.dentry->d_inode->i_mutex); | ||
| 3451 | path_put(&new_path); | ||
| 3452 | out: | 3565 | out: |
| 3453 | path_put(&old_path); | 3566 | path_put(&old_path); |
| 3454 | 3567 | ||
| @@ -3644,6 +3757,10 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | |||
| 3644 | if (newnd.last_type != LAST_NORM) | 3757 | if (newnd.last_type != LAST_NORM) |
| 3645 | goto exit2; | 3758 | goto exit2; |
| 3646 | 3759 | ||
| 3760 | error = mnt_want_write(oldnd.path.mnt); | ||
| 3761 | if (error) | ||
| 3762 | goto exit2; | ||
| 3763 | |||
| 3647 | oldnd.flags &= ~LOOKUP_PARENT; | 3764 | oldnd.flags &= ~LOOKUP_PARENT; |
| 3648 | newnd.flags &= ~LOOKUP_PARENT; | 3765 | newnd.flags &= ~LOOKUP_PARENT; |
| 3649 | newnd.flags |= LOOKUP_RENAME_TARGET; | 3766 | newnd.flags |= LOOKUP_RENAME_TARGET; |
| @@ -3679,23 +3796,19 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | |||
| 3679 | if (new_dentry == trap) | 3796 | if (new_dentry == trap) |
| 3680 | goto exit5; | 3797 | goto exit5; |
| 3681 | 3798 | ||
| 3682 | error = mnt_want_write(oldnd.path.mnt); | ||
| 3683 | if (error) | ||
| 3684 | goto exit5; | ||
| 3685 | error = security_path_rename(&oldnd.path, old_dentry, | 3799 | error = security_path_rename(&oldnd.path, old_dentry, |
| 3686 | &newnd.path, new_dentry); | 3800 | &newnd.path, new_dentry); |
| 3687 | if (error) | 3801 | if (error) |
| 3688 | goto exit6; | 3802 | goto exit5; |
| 3689 | error = vfs_rename(old_dir->d_inode, old_dentry, | 3803 | error = vfs_rename(old_dir->d_inode, old_dentry, |
| 3690 | new_dir->d_inode, new_dentry); | 3804 | new_dir->d_inode, new_dentry); |
| 3691 | exit6: | ||
| 3692 | mnt_drop_write(oldnd.path.mnt); | ||
| 3693 | exit5: | 3805 | exit5: |
| 3694 | dput(new_dentry); | 3806 | dput(new_dentry); |
| 3695 | exit4: | 3807 | exit4: |
| 3696 | dput(old_dentry); | 3808 | dput(old_dentry); |
| 3697 | exit3: | 3809 | exit3: |
| 3698 | unlock_rename(new_dir, old_dir); | 3810 | unlock_rename(new_dir, old_dir); |
| 3811 | mnt_drop_write(oldnd.path.mnt); | ||
| 3699 | exit2: | 3812 | exit2: |
| 3700 | path_put(&newnd.path); | 3813 | path_put(&newnd.path); |
| 3701 | putname(to); | 3814 | putname(to); |
diff --git a/fs/namespace.c b/fs/namespace.c index c53d3381b0d0..4d31f73e2561 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -283,24 +283,22 @@ static int mnt_is_readonly(struct vfsmount *mnt) | |||
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | /* | 285 | /* |
| 286 | * Most r/o checks on a fs are for operations that take | 286 | * Most r/o & frozen checks on a fs are for operations that take discrete |
| 287 | * discrete amounts of time, like a write() or unlink(). | 287 | * amounts of time, like a write() or unlink(). We must keep track of when |
| 288 | * We must keep track of when those operations start | 288 | * those operations start (for permission checks) and when they end, so that we |
| 289 | * (for permission checks) and when they end, so that | 289 | * can determine when writes are able to occur to a filesystem. |
| 290 | * we can determine when writes are able to occur to | ||
| 291 | * a filesystem. | ||
| 292 | */ | 290 | */ |
| 293 | /** | 291 | /** |
| 294 | * mnt_want_write - get write access to a mount | 292 | * __mnt_want_write - get write access to a mount without freeze protection |
| 295 | * @m: the mount on which to take a write | 293 | * @m: the mount on which to take a write |
| 296 | * | 294 | * |
| 297 | * This tells the low-level filesystem that a write is | 295 | * This tells the low-level filesystem that a write is about to be performed to |
| 298 | * about to be performed to it, and makes sure that | 296 | * it, and makes sure that writes are allowed (mnt it read-write) before |
| 299 | * writes are allowed before returning success. When | 297 | * returning success. This operation does not protect against filesystem being |
| 300 | * the write operation is finished, mnt_drop_write() | 298 | * frozen. When the write operation is finished, __mnt_drop_write() must be |
| 301 | * must be called. This is effectively a refcount. | 299 | * called. This is effectively a refcount. |
| 302 | */ | 300 | */ |
| 303 | int mnt_want_write(struct vfsmount *m) | 301 | int __mnt_want_write(struct vfsmount *m) |
| 304 | { | 302 | { |
| 305 | struct mount *mnt = real_mount(m); | 303 | struct mount *mnt = real_mount(m); |
| 306 | int ret = 0; | 304 | int ret = 0; |
| @@ -326,6 +324,27 @@ int mnt_want_write(struct vfsmount *m) | |||
| 326 | ret = -EROFS; | 324 | ret = -EROFS; |
| 327 | } | 325 | } |
| 328 | preempt_enable(); | 326 | preempt_enable(); |
| 327 | |||
| 328 | return ret; | ||
| 329 | } | ||
| 330 | |||
| 331 | /** | ||
| 332 | * mnt_want_write - get write access to a mount | ||
| 333 | * @m: the mount on which to take a write | ||
| 334 | * | ||
| 335 | * This tells the low-level filesystem that a write is about to be performed to | ||
| 336 | * it, and makes sure that writes are allowed (mount is read-write, filesystem | ||
| 337 | * is not frozen) before returning success. When the write operation is | ||
| 338 | * finished, mnt_drop_write() must be called. This is effectively a refcount. | ||
| 339 | */ | ||
| 340 | int mnt_want_write(struct vfsmount *m) | ||
| 341 | { | ||
| 342 | int ret; | ||
| 343 | |||
| 344 | sb_start_write(m->mnt_sb); | ||
| 345 | ret = __mnt_want_write(m); | ||
| 346 | if (ret) | ||
| 347 | sb_end_write(m->mnt_sb); | ||
| 329 | return ret; | 348 | return ret; |
| 330 | } | 349 | } |
| 331 | EXPORT_SYMBOL_GPL(mnt_want_write); | 350 | EXPORT_SYMBOL_GPL(mnt_want_write); |
| @@ -355,38 +374,76 @@ int mnt_clone_write(struct vfsmount *mnt) | |||
| 355 | EXPORT_SYMBOL_GPL(mnt_clone_write); | 374 | EXPORT_SYMBOL_GPL(mnt_clone_write); |
| 356 | 375 | ||
| 357 | /** | 376 | /** |
| 358 | * mnt_want_write_file - get write access to a file's mount | 377 | * __mnt_want_write_file - get write access to a file's mount |
| 359 | * @file: the file who's mount on which to take a write | 378 | * @file: the file who's mount on which to take a write |
| 360 | * | 379 | * |
| 361 | * This is like mnt_want_write, but it takes a file and can | 380 | * This is like __mnt_want_write, but it takes a file and can |
| 362 | * do some optimisations if the file is open for write already | 381 | * do some optimisations if the file is open for write already |
| 363 | */ | 382 | */ |
| 364 | int mnt_want_write_file(struct file *file) | 383 | int __mnt_want_write_file(struct file *file) |
| 365 | { | 384 | { |
| 366 | struct inode *inode = file->f_dentry->d_inode; | 385 | struct inode *inode = file->f_dentry->d_inode; |
| 386 | |||
| 367 | if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode)) | 387 | if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode)) |
| 368 | return mnt_want_write(file->f_path.mnt); | 388 | return __mnt_want_write(file->f_path.mnt); |
| 369 | else | 389 | else |
| 370 | return mnt_clone_write(file->f_path.mnt); | 390 | return mnt_clone_write(file->f_path.mnt); |
| 371 | } | 391 | } |
| 392 | |||
| 393 | /** | ||
| 394 | * mnt_want_write_file - get write access to a file's mount | ||
| 395 | * @file: the file who's mount on which to take a write | ||
| 396 | * | ||
| 397 | * This is like mnt_want_write, but it takes a file and can | ||
| 398 | * do some optimisations if the file is open for write already | ||
| 399 | */ | ||
| 400 | int mnt_want_write_file(struct file *file) | ||
| 401 | { | ||
| 402 | int ret; | ||
| 403 | |||
| 404 | sb_start_write(file->f_path.mnt->mnt_sb); | ||
| 405 | ret = __mnt_want_write_file(file); | ||
| 406 | if (ret) | ||
| 407 | sb_end_write(file->f_path.mnt->mnt_sb); | ||
| 408 | return ret; | ||
| 409 | } | ||
| 372 | EXPORT_SYMBOL_GPL(mnt_want_write_file); | 410 | EXPORT_SYMBOL_GPL(mnt_want_write_file); |
| 373 | 411 | ||
| 374 | /** | 412 | /** |
| 375 | * mnt_drop_write - give up write access to a mount | 413 | * __mnt_drop_write - give up write access to a mount |
| 376 | * @mnt: the mount on which to give up write access | 414 | * @mnt: the mount on which to give up write access |
| 377 | * | 415 | * |
| 378 | * Tells the low-level filesystem that we are done | 416 | * Tells the low-level filesystem that we are done |
| 379 | * performing writes to it. Must be matched with | 417 | * performing writes to it. Must be matched with |
| 380 | * mnt_want_write() call above. | 418 | * __mnt_want_write() call above. |
| 381 | */ | 419 | */ |
| 382 | void mnt_drop_write(struct vfsmount *mnt) | 420 | void __mnt_drop_write(struct vfsmount *mnt) |
| 383 | { | 421 | { |
| 384 | preempt_disable(); | 422 | preempt_disable(); |
| 385 | mnt_dec_writers(real_mount(mnt)); | 423 | mnt_dec_writers(real_mount(mnt)); |
| 386 | preempt_enable(); | 424 | preempt_enable(); |
| 387 | } | 425 | } |
| 426 | |||
| 427 | /** | ||
| 428 | * mnt_drop_write - give up write access to a mount | ||
| 429 | * @mnt: the mount on which to give up write access | ||
| 430 | * | ||
| 431 | * Tells the low-level filesystem that we are done performing writes to it and | ||
| 432 | * also allows filesystem to be frozen again. Must be matched with | ||
| 433 | * mnt_want_write() call above. | ||
| 434 | */ | ||
| 435 | void mnt_drop_write(struct vfsmount *mnt) | ||
| 436 | { | ||
| 437 | __mnt_drop_write(mnt); | ||
| 438 | sb_end_write(mnt->mnt_sb); | ||
| 439 | } | ||
| 388 | EXPORT_SYMBOL_GPL(mnt_drop_write); | 440 | EXPORT_SYMBOL_GPL(mnt_drop_write); |
| 389 | 441 | ||
| 442 | void __mnt_drop_write_file(struct file *file) | ||
| 443 | { | ||
| 444 | __mnt_drop_write(file->f_path.mnt); | ||
| 445 | } | ||
| 446 | |||
| 390 | void mnt_drop_write_file(struct file *file) | 447 | void mnt_drop_write_file(struct file *file) |
| 391 | { | 448 | { |
| 392 | mnt_drop_write(file->f_path.mnt); | 449 | mnt_drop_write(file->f_path.mnt); |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 5ff0b7b9fc08..43295d45cc2b 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
| @@ -154,6 +154,10 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) | |||
| 154 | if (status < 0) | 154 | if (status < 0) |
| 155 | return; | 155 | return; |
| 156 | 156 | ||
| 157 | status = mnt_want_write_file(rec_file); | ||
| 158 | if (status) | ||
| 159 | return; | ||
| 160 | |||
| 157 | dir = rec_file->f_path.dentry; | 161 | dir = rec_file->f_path.dentry; |
| 158 | /* lock the parent */ | 162 | /* lock the parent */ |
| 159 | mutex_lock(&dir->d_inode->i_mutex); | 163 | mutex_lock(&dir->d_inode->i_mutex); |
| @@ -173,11 +177,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) | |||
| 173 | * as well be forgiving and just succeed silently. | 177 | * as well be forgiving and just succeed silently. |
| 174 | */ | 178 | */ |
| 175 | goto out_put; | 179 | goto out_put; |
| 176 | status = mnt_want_write_file(rec_file); | ||
| 177 | if (status) | ||
| 178 | goto out_put; | ||
| 179 | status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU); | 180 | status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU); |
| 180 | mnt_drop_write_file(rec_file); | ||
| 181 | out_put: | 181 | out_put: |
| 182 | dput(dentry); | 182 | dput(dentry); |
| 183 | out_unlock: | 183 | out_unlock: |
| @@ -189,6 +189,7 @@ out_unlock: | |||
| 189 | " (err %d); please check that %s exists" | 189 | " (err %d); please check that %s exists" |
| 190 | " and is writeable", status, | 190 | " and is writeable", status, |
| 191 | user_recovery_dirname); | 191 | user_recovery_dirname); |
| 192 | mnt_drop_write_file(rec_file); | ||
| 192 | nfs4_reset_creds(original_cred); | 193 | nfs4_reset_creds(original_cred); |
| 193 | } | 194 | } |
| 194 | 195 | ||
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index cc793005a87c..032af381b3aa 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
| @@ -635,6 +635,7 @@ fh_put(struct svc_fh *fhp) | |||
| 635 | fhp->fh_post_saved = 0; | 635 | fhp->fh_post_saved = 0; |
| 636 | #endif | 636 | #endif |
| 637 | } | 637 | } |
| 638 | fh_drop_write(fhp); | ||
| 638 | if (exp) { | 639 | if (exp) { |
| 639 | exp_put(exp); | 640 | exp_put(exp); |
| 640 | fhp->fh_export = NULL; | 641 | fhp->fh_export = NULL; |
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index e15dc45fc5ec..aad6d457b9e8 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c | |||
| @@ -196,6 +196,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, | |||
| 196 | struct dentry *dchild; | 196 | struct dentry *dchild; |
| 197 | int type, mode; | 197 | int type, mode; |
| 198 | __be32 nfserr; | 198 | __be32 nfserr; |
| 199 | int hosterr; | ||
| 199 | dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size); | 200 | dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size); |
| 200 | 201 | ||
| 201 | dprintk("nfsd: CREATE %s %.*s\n", | 202 | dprintk("nfsd: CREATE %s %.*s\n", |
| @@ -214,6 +215,12 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, | |||
| 214 | nfserr = nfserr_exist; | 215 | nfserr = nfserr_exist; |
| 215 | if (isdotent(argp->name, argp->len)) | 216 | if (isdotent(argp->name, argp->len)) |
| 216 | goto done; | 217 | goto done; |
| 218 | hosterr = fh_want_write(dirfhp); | ||
| 219 | if (hosterr) { | ||
| 220 | nfserr = nfserrno(hosterr); | ||
| 221 | goto done; | ||
| 222 | } | ||
| 223 | |||
| 217 | fh_lock_nested(dirfhp, I_MUTEX_PARENT); | 224 | fh_lock_nested(dirfhp, I_MUTEX_PARENT); |
| 218 | dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len); | 225 | dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len); |
| 219 | if (IS_ERR(dchild)) { | 226 | if (IS_ERR(dchild)) { |
| @@ -330,7 +337,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, | |||
| 330 | out_unlock: | 337 | out_unlock: |
| 331 | /* We don't really need to unlock, as fh_put does it. */ | 338 | /* We don't really need to unlock, as fh_put does it. */ |
| 332 | fh_unlock(dirfhp); | 339 | fh_unlock(dirfhp); |
| 333 | 340 | fh_drop_write(dirfhp); | |
| 334 | done: | 341 | done: |
| 335 | fh_put(dirfhp); | 342 | fh_put(dirfhp); |
| 336 | return nfsd_return_dirop(nfserr, resp); | 343 | return nfsd_return_dirop(nfserr, resp); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 702f64e820c3..a9269f142cc4 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -1284,6 +1284,10 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1284 | * If it has, the parent directory should already be locked. | 1284 | * If it has, the parent directory should already be locked. |
| 1285 | */ | 1285 | */ |
| 1286 | if (!resfhp->fh_dentry) { | 1286 | if (!resfhp->fh_dentry) { |
| 1287 | host_err = fh_want_write(fhp); | ||
| 1288 | if (host_err) | ||
| 1289 | goto out_nfserr; | ||
| 1290 | |||
| 1287 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ | 1291 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ |
| 1288 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1292 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
| 1289 | dchild = lookup_one_len(fname, dentry, flen); | 1293 | dchild = lookup_one_len(fname, dentry, flen); |
| @@ -1327,14 +1331,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1327 | goto out; | 1331 | goto out; |
| 1328 | } | 1332 | } |
| 1329 | 1333 | ||
| 1330 | host_err = fh_want_write(fhp); | ||
| 1331 | if (host_err) | ||
| 1332 | goto out_nfserr; | ||
| 1333 | |||
| 1334 | /* | 1334 | /* |
| 1335 | * Get the dir op function pointer. | 1335 | * Get the dir op function pointer. |
| 1336 | */ | 1336 | */ |
| 1337 | err = 0; | 1337 | err = 0; |
| 1338 | host_err = 0; | ||
| 1338 | switch (type) { | 1339 | switch (type) { |
| 1339 | case S_IFREG: | 1340 | case S_IFREG: |
| 1340 | host_err = vfs_create(dirp, dchild, iap->ia_mode, true); | 1341 | host_err = vfs_create(dirp, dchild, iap->ia_mode, true); |
| @@ -1351,10 +1352,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1351 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); | 1352 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); |
| 1352 | break; | 1353 | break; |
| 1353 | } | 1354 | } |
| 1354 | if (host_err < 0) { | 1355 | if (host_err < 0) |
| 1355 | fh_drop_write(fhp); | ||
| 1356 | goto out_nfserr; | 1356 | goto out_nfserr; |
| 1357 | } | ||
| 1358 | 1357 | ||
| 1359 | err = nfsd_create_setattr(rqstp, resfhp, iap); | 1358 | err = nfsd_create_setattr(rqstp, resfhp, iap); |
| 1360 | 1359 | ||
| @@ -1366,7 +1365,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1366 | err2 = nfserrno(commit_metadata(fhp)); | 1365 | err2 = nfserrno(commit_metadata(fhp)); |
| 1367 | if (err2) | 1366 | if (err2) |
| 1368 | err = err2; | 1367 | err = err2; |
| 1369 | fh_drop_write(fhp); | ||
| 1370 | /* | 1368 | /* |
| 1371 | * Update the file handle to get the new inode info. | 1369 | * Update the file handle to get the new inode info. |
| 1372 | */ | 1370 | */ |
| @@ -1425,6 +1423,11 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1425 | err = nfserr_notdir; | 1423 | err = nfserr_notdir; |
| 1426 | if (!dirp->i_op->lookup) | 1424 | if (!dirp->i_op->lookup) |
| 1427 | goto out; | 1425 | goto out; |
| 1426 | |||
| 1427 | host_err = fh_want_write(fhp); | ||
| 1428 | if (host_err) | ||
| 1429 | goto out_nfserr; | ||
| 1430 | |||
| 1428 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1431 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
| 1429 | 1432 | ||
| 1430 | /* | 1433 | /* |
| @@ -1457,9 +1460,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1457 | v_atime = verifier[1]&0x7fffffff; | 1460 | v_atime = verifier[1]&0x7fffffff; |
| 1458 | } | 1461 | } |
| 1459 | 1462 | ||
| 1460 | host_err = fh_want_write(fhp); | ||
| 1461 | if (host_err) | ||
| 1462 | goto out_nfserr; | ||
| 1463 | if (dchild->d_inode) { | 1463 | if (dchild->d_inode) { |
| 1464 | err = 0; | 1464 | err = 0; |
| 1465 | 1465 | ||
| @@ -1530,7 +1530,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1530 | if (!err) | 1530 | if (!err) |
| 1531 | err = nfserrno(commit_metadata(fhp)); | 1531 | err = nfserrno(commit_metadata(fhp)); |
| 1532 | 1532 | ||
| 1533 | fh_drop_write(fhp); | ||
| 1534 | /* | 1533 | /* |
| 1535 | * Update the filehandle to get the new inode info. | 1534 | * Update the filehandle to get the new inode info. |
| 1536 | */ | 1535 | */ |
| @@ -1541,6 +1540,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1541 | fh_unlock(fhp); | 1540 | fh_unlock(fhp); |
| 1542 | if (dchild && !IS_ERR(dchild)) | 1541 | if (dchild && !IS_ERR(dchild)) |
| 1543 | dput(dchild); | 1542 | dput(dchild); |
| 1543 | fh_drop_write(fhp); | ||
| 1544 | return err; | 1544 | return err; |
| 1545 | 1545 | ||
| 1546 | out_nfserr: | 1546 | out_nfserr: |
| @@ -1621,6 +1621,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1621 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); | 1621 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); |
| 1622 | if (err) | 1622 | if (err) |
| 1623 | goto out; | 1623 | goto out; |
| 1624 | |||
| 1625 | host_err = fh_want_write(fhp); | ||
| 1626 | if (host_err) | ||
| 1627 | goto out_nfserr; | ||
| 1628 | |||
| 1624 | fh_lock(fhp); | 1629 | fh_lock(fhp); |
| 1625 | dentry = fhp->fh_dentry; | 1630 | dentry = fhp->fh_dentry; |
| 1626 | dnew = lookup_one_len(fname, dentry, flen); | 1631 | dnew = lookup_one_len(fname, dentry, flen); |
| @@ -1628,10 +1633,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1628 | if (IS_ERR(dnew)) | 1633 | if (IS_ERR(dnew)) |
| 1629 | goto out_nfserr; | 1634 | goto out_nfserr; |
| 1630 | 1635 | ||
| 1631 | host_err = fh_want_write(fhp); | ||
| 1632 | if (host_err) | ||
| 1633 | goto out_nfserr; | ||
| 1634 | |||
| 1635 | if (unlikely(path[plen] != 0)) { | 1636 | if (unlikely(path[plen] != 0)) { |
| 1636 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); | 1637 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); |
| 1637 | if (path_alloced == NULL) | 1638 | if (path_alloced == NULL) |
| @@ -1691,6 +1692,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
| 1691 | if (isdotent(name, len)) | 1692 | if (isdotent(name, len)) |
| 1692 | goto out; | 1693 | goto out; |
| 1693 | 1694 | ||
| 1695 | host_err = fh_want_write(tfhp); | ||
| 1696 | if (host_err) { | ||
| 1697 | err = nfserrno(host_err); | ||
| 1698 | goto out; | ||
| 1699 | } | ||
| 1700 | |||
| 1694 | fh_lock_nested(ffhp, I_MUTEX_PARENT); | 1701 | fh_lock_nested(ffhp, I_MUTEX_PARENT); |
| 1695 | ddir = ffhp->fh_dentry; | 1702 | ddir = ffhp->fh_dentry; |
| 1696 | dirp = ddir->d_inode; | 1703 | dirp = ddir->d_inode; |
| @@ -1702,18 +1709,13 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
| 1702 | 1709 | ||
| 1703 | dold = tfhp->fh_dentry; | 1710 | dold = tfhp->fh_dentry; |
| 1704 | 1711 | ||
| 1705 | host_err = fh_want_write(tfhp); | ||
| 1706 | if (host_err) { | ||
| 1707 | err = nfserrno(host_err); | ||
| 1708 | goto out_dput; | ||
| 1709 | } | ||
| 1710 | err = nfserr_noent; | 1712 | err = nfserr_noent; |
| 1711 | if (!dold->d_inode) | 1713 | if (!dold->d_inode) |
| 1712 | goto out_drop_write; | 1714 | goto out_dput; |
| 1713 | host_err = nfsd_break_lease(dold->d_inode); | 1715 | host_err = nfsd_break_lease(dold->d_inode); |
| 1714 | if (host_err) { | 1716 | if (host_err) { |
| 1715 | err = nfserrno(host_err); | 1717 | err = nfserrno(host_err); |
| 1716 | goto out_drop_write; | 1718 | goto out_dput; |
| 1717 | } | 1719 | } |
| 1718 | host_err = vfs_link(dold, dirp, dnew); | 1720 | host_err = vfs_link(dold, dirp, dnew); |
| 1719 | if (!host_err) { | 1721 | if (!host_err) { |
| @@ -1726,12 +1728,11 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
| 1726 | else | 1728 | else |
| 1727 | err = nfserrno(host_err); | 1729 | err = nfserrno(host_err); |
| 1728 | } | 1730 | } |
| 1729 | out_drop_write: | ||
| 1730 | fh_drop_write(tfhp); | ||
| 1731 | out_dput: | 1731 | out_dput: |
| 1732 | dput(dnew); | 1732 | dput(dnew); |
| 1733 | out_unlock: | 1733 | out_unlock: |
| 1734 | fh_unlock(ffhp); | 1734 | fh_unlock(ffhp); |
| 1735 | fh_drop_write(tfhp); | ||
| 1735 | out: | 1736 | out: |
| 1736 | return err; | 1737 | return err; |
| 1737 | 1738 | ||
| @@ -1774,6 +1775,12 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
| 1774 | if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) | 1775 | if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) |
| 1775 | goto out; | 1776 | goto out; |
| 1776 | 1777 | ||
| 1778 | host_err = fh_want_write(ffhp); | ||
| 1779 | if (host_err) { | ||
| 1780 | err = nfserrno(host_err); | ||
| 1781 | goto out; | ||
| 1782 | } | ||
| 1783 | |||
| 1777 | /* cannot use fh_lock as we need deadlock protective ordering | 1784 | /* cannot use fh_lock as we need deadlock protective ordering |
| 1778 | * so do it by hand */ | 1785 | * so do it by hand */ |
| 1779 | trap = lock_rename(tdentry, fdentry); | 1786 | trap = lock_rename(tdentry, fdentry); |
| @@ -1804,17 +1811,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
| 1804 | host_err = -EXDEV; | 1811 | host_err = -EXDEV; |
| 1805 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) | 1812 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) |
| 1806 | goto out_dput_new; | 1813 | goto out_dput_new; |
| 1807 | host_err = fh_want_write(ffhp); | ||
| 1808 | if (host_err) | ||
| 1809 | goto out_dput_new; | ||
| 1810 | 1814 | ||
| 1811 | host_err = nfsd_break_lease(odentry->d_inode); | 1815 | host_err = nfsd_break_lease(odentry->d_inode); |
| 1812 | if (host_err) | 1816 | if (host_err) |
| 1813 | goto out_drop_write; | 1817 | goto out_dput_new; |
| 1814 | if (ndentry->d_inode) { | 1818 | if (ndentry->d_inode) { |
| 1815 | host_err = nfsd_break_lease(ndentry->d_inode); | 1819 | host_err = nfsd_break_lease(ndentry->d_inode); |
| 1816 | if (host_err) | 1820 | if (host_err) |
| 1817 | goto out_drop_write; | 1821 | goto out_dput_new; |
| 1818 | } | 1822 | } |
| 1819 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); | 1823 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); |
| 1820 | if (!host_err) { | 1824 | if (!host_err) { |
| @@ -1822,8 +1826,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
| 1822 | if (!host_err) | 1826 | if (!host_err) |
| 1823 | host_err = commit_metadata(ffhp); | 1827 | host_err = commit_metadata(ffhp); |
| 1824 | } | 1828 | } |
| 1825 | out_drop_write: | ||
| 1826 | fh_drop_write(ffhp); | ||
| 1827 | out_dput_new: | 1829 | out_dput_new: |
| 1828 | dput(ndentry); | 1830 | dput(ndentry); |
| 1829 | out_dput_old: | 1831 | out_dput_old: |
| @@ -1839,6 +1841,7 @@ out_drop_write: | |||
| 1839 | fill_post_wcc(tfhp); | 1841 | fill_post_wcc(tfhp); |
| 1840 | unlock_rename(tdentry, fdentry); | 1842 | unlock_rename(tdentry, fdentry); |
| 1841 | ffhp->fh_locked = tfhp->fh_locked = 0; | 1843 | ffhp->fh_locked = tfhp->fh_locked = 0; |
| 1844 | fh_drop_write(ffhp); | ||
| 1842 | 1845 | ||
| 1843 | out: | 1846 | out: |
| 1844 | return err; | 1847 | return err; |
| @@ -1864,6 +1867,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
| 1864 | if (err) | 1867 | if (err) |
| 1865 | goto out; | 1868 | goto out; |
| 1866 | 1869 | ||
| 1870 | host_err = fh_want_write(fhp); | ||
| 1871 | if (host_err) | ||
| 1872 | goto out_nfserr; | ||
| 1873 | |||
| 1867 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1874 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
| 1868 | dentry = fhp->fh_dentry; | 1875 | dentry = fhp->fh_dentry; |
| 1869 | dirp = dentry->d_inode; | 1876 | dirp = dentry->d_inode; |
| @@ -1882,21 +1889,15 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
| 1882 | if (!type) | 1889 | if (!type) |
| 1883 | type = rdentry->d_inode->i_mode & S_IFMT; | 1890 | type = rdentry->d_inode->i_mode & S_IFMT; |
| 1884 | 1891 | ||
| 1885 | host_err = fh_want_write(fhp); | ||
| 1886 | if (host_err) | ||
| 1887 | goto out_put; | ||
| 1888 | |||
| 1889 | host_err = nfsd_break_lease(rdentry->d_inode); | 1892 | host_err = nfsd_break_lease(rdentry->d_inode); |
| 1890 | if (host_err) | 1893 | if (host_err) |
| 1891 | goto out_drop_write; | 1894 | goto out_put; |
| 1892 | if (type != S_IFDIR) | 1895 | if (type != S_IFDIR) |
| 1893 | host_err = vfs_unlink(dirp, rdentry); | 1896 | host_err = vfs_unlink(dirp, rdentry); |
| 1894 | else | 1897 | else |
| 1895 | host_err = vfs_rmdir(dirp, rdentry); | 1898 | host_err = vfs_rmdir(dirp, rdentry); |
| 1896 | if (!host_err) | 1899 | if (!host_err) |
| 1897 | host_err = commit_metadata(fhp); | 1900 | host_err = commit_metadata(fhp); |
| 1898 | out_drop_write: | ||
| 1899 | fh_drop_write(fhp); | ||
| 1900 | out_put: | 1901 | out_put: |
| 1901 | dput(rdentry); | 1902 | dput(rdentry); |
| 1902 | 1903 | ||
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index ec0611b2b738..359594c393d2 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h | |||
| @@ -110,12 +110,19 @@ int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *); | |||
| 110 | 110 | ||
| 111 | static inline int fh_want_write(struct svc_fh *fh) | 111 | static inline int fh_want_write(struct svc_fh *fh) |
| 112 | { | 112 | { |
| 113 | return mnt_want_write(fh->fh_export->ex_path.mnt); | 113 | int ret = mnt_want_write(fh->fh_export->ex_path.mnt); |
| 114 | |||
| 115 | if (!ret) | ||
| 116 | fh->fh_want_write = 1; | ||
| 117 | return ret; | ||
| 114 | } | 118 | } |
| 115 | 119 | ||
| 116 | static inline void fh_drop_write(struct svc_fh *fh) | 120 | static inline void fh_drop_write(struct svc_fh *fh) |
| 117 | { | 121 | { |
| 118 | mnt_drop_write(fh->fh_export->ex_path.mnt); | 122 | if (fh->fh_want_write) { |
| 123 | fh->fh_want_write = 0; | ||
| 124 | mnt_drop_write(fh->fh_export->ex_path.mnt); | ||
| 125 | } | ||
| 119 | } | 126 | } |
| 120 | 127 | ||
| 121 | #endif /* LINUX_NFSD_VFS_H */ | 128 | #endif /* LINUX_NFSD_VFS_H */ |
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 62cebc8e1a1f..a4d56ac02e6c 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c | |||
| @@ -69,16 +69,18 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 69 | struct page *page = vmf->page; | 69 | struct page *page = vmf->page; |
| 70 | struct inode *inode = vma->vm_file->f_dentry->d_inode; | 70 | struct inode *inode = vma->vm_file->f_dentry->d_inode; |
| 71 | struct nilfs_transaction_info ti; | 71 | struct nilfs_transaction_info ti; |
| 72 | int ret; | 72 | int ret = 0; |
| 73 | 73 | ||
| 74 | if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info))) | 74 | if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info))) |
| 75 | return VM_FAULT_SIGBUS; /* -ENOSPC */ | 75 | return VM_FAULT_SIGBUS; /* -ENOSPC */ |
| 76 | 76 | ||
| 77 | sb_start_pagefault(inode->i_sb); | ||
| 77 | lock_page(page); | 78 | lock_page(page); |
| 78 | if (page->mapping != inode->i_mapping || | 79 | if (page->mapping != inode->i_mapping || |
| 79 | page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) { | 80 | page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) { |
| 80 | unlock_page(page); | 81 | unlock_page(page); |
| 81 | return VM_FAULT_NOPAGE; /* make the VM retry the fault */ | 82 | ret = -EFAULT; /* make the VM retry the fault */ |
| 83 | goto out; | ||
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | /* | 86 | /* |
| @@ -112,19 +114,21 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 112 | ret = nilfs_transaction_begin(inode->i_sb, &ti, 1); | 114 | ret = nilfs_transaction_begin(inode->i_sb, &ti, 1); |
| 113 | /* never returns -ENOMEM, but may return -ENOSPC */ | 115 | /* never returns -ENOMEM, but may return -ENOSPC */ |
| 114 | if (unlikely(ret)) | 116 | if (unlikely(ret)) |
| 115 | return VM_FAULT_SIGBUS; | 117 | goto out; |
| 116 | 118 | ||
| 117 | ret = block_page_mkwrite(vma, vmf, nilfs_get_block); | 119 | ret = __block_page_mkwrite(vma, vmf, nilfs_get_block); |
| 118 | if (ret != VM_FAULT_LOCKED) { | 120 | if (ret) { |
| 119 | nilfs_transaction_abort(inode->i_sb); | 121 | nilfs_transaction_abort(inode->i_sb); |
| 120 | return ret; | 122 | goto out; |
| 121 | } | 123 | } |
| 122 | nilfs_set_file_dirty(inode, 1 << (PAGE_SHIFT - inode->i_blkbits)); | 124 | nilfs_set_file_dirty(inode, 1 << (PAGE_SHIFT - inode->i_blkbits)); |
| 123 | nilfs_transaction_commit(inode->i_sb); | 125 | nilfs_transaction_commit(inode->i_sb); |
| 124 | 126 | ||
| 125 | mapped: | 127 | mapped: |
| 126 | wait_on_page_writeback(page); | 128 | wait_on_page_writeback(page); |
| 127 | return VM_FAULT_LOCKED; | 129 | out: |
| 130 | sb_end_pagefault(inode->i_sb); | ||
| 131 | return block_page_mkwrite_return(ret); | ||
| 128 | } | 132 | } |
| 129 | 133 | ||
| 130 | static const struct vm_operations_struct nilfs_file_vm_ops = { | 134 | static const struct vm_operations_struct nilfs_file_vm_ops = { |
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 0b6387c67e6c..fdb180769485 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -660,8 +660,6 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 660 | goto out_free; | 660 | goto out_free; |
| 661 | } | 661 | } |
| 662 | 662 | ||
| 663 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
| 664 | |||
| 665 | ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); | 663 | ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); |
| 666 | if (ret < 0) | 664 | if (ret < 0) |
| 667 | printk(KERN_ERR "NILFS: GC failed during preparation: " | 665 | printk(KERN_ERR "NILFS: GC failed during preparation: " |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 88e11fb346b6..a5752a589932 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -189,7 +189,7 @@ int nilfs_transaction_begin(struct super_block *sb, | |||
| 189 | if (ret > 0) | 189 | if (ret > 0) |
| 190 | return 0; | 190 | return 0; |
| 191 | 191 | ||
| 192 | vfs_check_frozen(sb, SB_FREEZE_WRITE); | 192 | sb_start_intwrite(sb); |
| 193 | 193 | ||
| 194 | nilfs = sb->s_fs_info; | 194 | nilfs = sb->s_fs_info; |
| 195 | down_read(&nilfs->ns_segctor_sem); | 195 | down_read(&nilfs->ns_segctor_sem); |
| @@ -205,6 +205,7 @@ int nilfs_transaction_begin(struct super_block *sb, | |||
| 205 | current->journal_info = ti->ti_save; | 205 | current->journal_info = ti->ti_save; |
| 206 | if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) | 206 | if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) |
| 207 | kmem_cache_free(nilfs_transaction_cachep, ti); | 207 | kmem_cache_free(nilfs_transaction_cachep, ti); |
| 208 | sb_end_intwrite(sb); | ||
| 208 | return ret; | 209 | return ret; |
| 209 | } | 210 | } |
| 210 | 211 | ||
| @@ -246,6 +247,7 @@ int nilfs_transaction_commit(struct super_block *sb) | |||
| 246 | err = nilfs_construct_segment(sb); | 247 | err = nilfs_construct_segment(sb); |
| 247 | if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) | 248 | if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) |
| 248 | kmem_cache_free(nilfs_transaction_cachep, ti); | 249 | kmem_cache_free(nilfs_transaction_cachep, ti); |
| 250 | sb_end_intwrite(sb); | ||
| 249 | return err; | 251 | return err; |
| 250 | } | 252 | } |
| 251 | 253 | ||
| @@ -264,6 +266,7 @@ void nilfs_transaction_abort(struct super_block *sb) | |||
| 264 | current->journal_info = ti->ti_save; | 266 | current->journal_info = ti->ti_save; |
| 265 | if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) | 267 | if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) |
| 266 | kmem_cache_free(nilfs_transaction_cachep, ti); | 268 | kmem_cache_free(nilfs_transaction_cachep, ti); |
| 269 | sb_end_intwrite(sb); | ||
| 267 | } | 270 | } |
| 268 | 271 | ||
| 269 | void nilfs_relax_pressure_in_lock(struct super_block *sb) | 272 | void nilfs_relax_pressure_in_lock(struct super_block *sb) |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 7389d2d5e51d..1ecf46448f85 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
| @@ -2084,7 +2084,6 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb, | |||
| 2084 | if (err) | 2084 | if (err) |
| 2085 | return err; | 2085 | return err; |
| 2086 | pos = *ppos; | 2086 | pos = *ppos; |
| 2087 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
| 2088 | /* We can write back this queue in page reclaim. */ | 2087 | /* We can write back this queue in page reclaim. */ |
| 2089 | current->backing_dev_info = mapping->backing_dev_info; | 2088 | current->backing_dev_info = mapping->backing_dev_info; |
| 2090 | written = 0; | 2089 | written = 0; |
| @@ -2119,6 +2118,7 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 2119 | 2118 | ||
| 2120 | BUG_ON(iocb->ki_pos != pos); | 2119 | BUG_ON(iocb->ki_pos != pos); |
| 2121 | 2120 | ||
| 2121 | sb_start_write(inode->i_sb); | ||
| 2122 | mutex_lock(&inode->i_mutex); | 2122 | mutex_lock(&inode->i_mutex); |
| 2123 | ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos); | 2123 | ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos); |
| 2124 | mutex_unlock(&inode->i_mutex); | 2124 | mutex_unlock(&inode->i_mutex); |
| @@ -2127,6 +2127,7 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 2127 | if (err < 0) | 2127 | if (err < 0) |
| 2128 | ret = err; | 2128 | ret = err; |
| 2129 | } | 2129 | } |
| 2130 | sb_end_write(inode->i_sb); | ||
| 2130 | return ret; | 2131 | return ret; |
| 2131 | } | 2132 | } |
| 2132 | 2133 | ||
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 7602783d7f41..46a1f6d75104 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -1971,6 +1971,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, | |||
| 1971 | { | 1971 | { |
| 1972 | struct inode *inode = file->f_path.dentry->d_inode; | 1972 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1973 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1973 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 1974 | int ret; | ||
| 1974 | 1975 | ||
| 1975 | if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) && | 1976 | if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) && |
| 1976 | !ocfs2_writes_unwritten_extents(osb)) | 1977 | !ocfs2_writes_unwritten_extents(osb)) |
| @@ -1985,7 +1986,12 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, | |||
| 1985 | if (!(file->f_mode & FMODE_WRITE)) | 1986 | if (!(file->f_mode & FMODE_WRITE)) |
| 1986 | return -EBADF; | 1987 | return -EBADF; |
| 1987 | 1988 | ||
| 1988 | return __ocfs2_change_file_space(file, inode, file->f_pos, cmd, sr, 0); | 1989 | ret = mnt_want_write_file(file); |
| 1990 | if (ret) | ||
| 1991 | return ret; | ||
| 1992 | ret = __ocfs2_change_file_space(file, inode, file->f_pos, cmd, sr, 0); | ||
| 1993 | mnt_drop_write_file(file); | ||
| 1994 | return ret; | ||
| 1989 | } | 1995 | } |
| 1990 | 1996 | ||
| 1991 | static long ocfs2_fallocate(struct file *file, int mode, loff_t offset, | 1997 | static long ocfs2_fallocate(struct file *file, int mode, loff_t offset, |
| @@ -2261,7 +2267,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | |||
| 2261 | if (iocb->ki_left == 0) | 2267 | if (iocb->ki_left == 0) |
| 2262 | return 0; | 2268 | return 0; |
| 2263 | 2269 | ||
| 2264 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 2270 | sb_start_write(inode->i_sb); |
| 2265 | 2271 | ||
| 2266 | appending = file->f_flags & O_APPEND ? 1 : 0; | 2272 | appending = file->f_flags & O_APPEND ? 1 : 0; |
| 2267 | direct_io = file->f_flags & O_DIRECT ? 1 : 0; | 2273 | direct_io = file->f_flags & O_DIRECT ? 1 : 0; |
| @@ -2436,6 +2442,7 @@ out_sems: | |||
| 2436 | ocfs2_iocb_clear_sem_locked(iocb); | 2442 | ocfs2_iocb_clear_sem_locked(iocb); |
| 2437 | 2443 | ||
| 2438 | mutex_unlock(&inode->i_mutex); | 2444 | mutex_unlock(&inode->i_mutex); |
| 2445 | sb_end_write(inode->i_sb); | ||
| 2439 | 2446 | ||
| 2440 | if (written) | 2447 | if (written) |
| 2441 | ret = written; | 2448 | ret = written; |
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index d96f7f81d8dd..f20edcbfe700 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c | |||
| @@ -928,7 +928,12 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 928 | if (get_user(new_clusters, (int __user *)arg)) | 928 | if (get_user(new_clusters, (int __user *)arg)) |
| 929 | return -EFAULT; | 929 | return -EFAULT; |
| 930 | 930 | ||
| 931 | return ocfs2_group_extend(inode, new_clusters); | 931 | status = mnt_want_write_file(filp); |
| 932 | if (status) | ||
| 933 | return status; | ||
| 934 | status = ocfs2_group_extend(inode, new_clusters); | ||
| 935 | mnt_drop_write_file(filp); | ||
| 936 | return status; | ||
| 932 | case OCFS2_IOC_GROUP_ADD: | 937 | case OCFS2_IOC_GROUP_ADD: |
| 933 | case OCFS2_IOC_GROUP_ADD64: | 938 | case OCFS2_IOC_GROUP_ADD64: |
| 934 | if (!capable(CAP_SYS_RESOURCE)) | 939 | if (!capable(CAP_SYS_RESOURCE)) |
| @@ -937,7 +942,12 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 937 | if (copy_from_user(&input, (int __user *) arg, sizeof(input))) | 942 | if (copy_from_user(&input, (int __user *) arg, sizeof(input))) |
| 938 | return -EFAULT; | 943 | return -EFAULT; |
| 939 | 944 | ||
| 940 | return ocfs2_group_add(inode, &input); | 945 | status = mnt_want_write_file(filp); |
| 946 | if (status) | ||
| 947 | return status; | ||
| 948 | status = ocfs2_group_add(inode, &input); | ||
| 949 | mnt_drop_write_file(filp); | ||
| 950 | return status; | ||
| 941 | case OCFS2_IOC_REFLINK: | 951 | case OCFS2_IOC_REFLINK: |
| 942 | if (copy_from_user(&args, argp, sizeof(args))) | 952 | if (copy_from_user(&args, argp, sizeof(args))) |
| 943 | return -EFAULT; | 953 | return -EFAULT; |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 0a42ae96dca7..2dd36af79e26 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
| @@ -355,11 +355,14 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs) | |||
| 355 | if (journal_current_handle()) | 355 | if (journal_current_handle()) |
| 356 | return jbd2_journal_start(journal, max_buffs); | 356 | return jbd2_journal_start(journal, max_buffs); |
| 357 | 357 | ||
| 358 | sb_start_intwrite(osb->sb); | ||
| 359 | |||
| 358 | down_read(&osb->journal->j_trans_barrier); | 360 | down_read(&osb->journal->j_trans_barrier); |
| 359 | 361 | ||
| 360 | handle = jbd2_journal_start(journal, max_buffs); | 362 | handle = jbd2_journal_start(journal, max_buffs); |
| 361 | if (IS_ERR(handle)) { | 363 | if (IS_ERR(handle)) { |
| 362 | up_read(&osb->journal->j_trans_barrier); | 364 | up_read(&osb->journal->j_trans_barrier); |
| 365 | sb_end_intwrite(osb->sb); | ||
| 363 | 366 | ||
| 364 | mlog_errno(PTR_ERR(handle)); | 367 | mlog_errno(PTR_ERR(handle)); |
| 365 | 368 | ||
| @@ -388,8 +391,10 @@ int ocfs2_commit_trans(struct ocfs2_super *osb, | |||
| 388 | if (ret < 0) | 391 | if (ret < 0) |
| 389 | mlog_errno(ret); | 392 | mlog_errno(ret); |
| 390 | 393 | ||
| 391 | if (!nested) | 394 | if (!nested) { |
| 392 | up_read(&journal->j_trans_barrier); | 395 | up_read(&journal->j_trans_barrier); |
| 396 | sb_end_intwrite(osb->sb); | ||
| 397 | } | ||
| 393 | 398 | ||
| 394 | return ret; | 399 | return ret; |
| 395 | } | 400 | } |
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 9cd41083e991..d150372fd81d 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c | |||
| @@ -136,6 +136,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 136 | sigset_t oldset; | 136 | sigset_t oldset; |
| 137 | int ret; | 137 | int ret; |
| 138 | 138 | ||
| 139 | sb_start_pagefault(inode->i_sb); | ||
| 139 | ocfs2_block_signals(&oldset); | 140 | ocfs2_block_signals(&oldset); |
| 140 | 141 | ||
| 141 | /* | 142 | /* |
| @@ -165,6 +166,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 165 | 166 | ||
| 166 | out: | 167 | out: |
| 167 | ocfs2_unblock_signals(&oldset); | 168 | ocfs2_unblock_signals(&oldset); |
| 169 | sb_end_pagefault(inode->i_sb); | ||
| 168 | return ret; | 170 | return ret; |
| 169 | } | 171 | } |
| 170 | 172 | ||
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 9f32d7cbb7a3..30a055049e16 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
| @@ -4466,20 +4466,11 @@ int ocfs2_reflink_ioctl(struct inode *inode, | |||
| 4466 | goto out_dput; | 4466 | goto out_dput; |
| 4467 | } | 4467 | } |
| 4468 | 4468 | ||
| 4469 | error = mnt_want_write(new_path.mnt); | ||
| 4470 | if (error) { | ||
| 4471 | mlog_errno(error); | ||
| 4472 | goto out_dput; | ||
| 4473 | } | ||
| 4474 | |||
| 4475 | error = ocfs2_vfs_reflink(old_path.dentry, | 4469 | error = ocfs2_vfs_reflink(old_path.dentry, |
| 4476 | new_path.dentry->d_inode, | 4470 | new_path.dentry->d_inode, |
| 4477 | new_dentry, preserve); | 4471 | new_dentry, preserve); |
| 4478 | mnt_drop_write(new_path.mnt); | ||
| 4479 | out_dput: | 4472 | out_dput: |
| 4480 | dput(new_dentry); | 4473 | done_path_create(&new_path, new_dentry); |
| 4481 | mutex_unlock(&new_path.dentry->d_inode->i_mutex); | ||
| 4482 | path_put(&new_path); | ||
| 4483 | out: | 4474 | out: |
| 4484 | path_put(&old_path); | 4475 | path_put(&old_path); |
| 4485 | 4476 | ||
| @@ -164,11 +164,13 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) | |||
| 164 | if (IS_APPEND(inode)) | 164 | if (IS_APPEND(inode)) |
| 165 | goto out_putf; | 165 | goto out_putf; |
| 166 | 166 | ||
| 167 | sb_start_write(inode->i_sb); | ||
| 167 | error = locks_verify_truncate(inode, file, length); | 168 | error = locks_verify_truncate(inode, file, length); |
| 168 | if (!error) | 169 | if (!error) |
| 169 | error = security_path_truncate(&file->f_path); | 170 | error = security_path_truncate(&file->f_path); |
| 170 | if (!error) | 171 | if (!error) |
| 171 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); | 172 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); |
| 173 | sb_end_write(inode->i_sb); | ||
| 172 | out_putf: | 174 | out_putf: |
| 173 | fput(file); | 175 | fput(file); |
| 174 | out: | 176 | out: |
| @@ -266,7 +268,10 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
| 266 | if (!file->f_op->fallocate) | 268 | if (!file->f_op->fallocate) |
| 267 | return -EOPNOTSUPP; | 269 | return -EOPNOTSUPP; |
| 268 | 270 | ||
| 269 | return file->f_op->fallocate(file, mode, offset, len); | 271 | sb_start_write(inode->i_sb); |
| 272 | ret = file->f_op->fallocate(file, mode, offset, len); | ||
| 273 | sb_end_write(inode->i_sb); | ||
| 274 | return ret; | ||
| 270 | } | 275 | } |
| 271 | 276 | ||
| 272 | SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len) | 277 | SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len) |
| @@ -620,7 +625,7 @@ static inline int __get_file_write_access(struct inode *inode, | |||
| 620 | /* | 625 | /* |
| 621 | * Balanced in __fput() | 626 | * Balanced in __fput() |
| 622 | */ | 627 | */ |
| 623 | error = mnt_want_write(mnt); | 628 | error = __mnt_want_write(mnt); |
| 624 | if (error) | 629 | if (error) |
| 625 | put_write_access(inode); | 630 | put_write_access(inode); |
| 626 | } | 631 | } |
| @@ -654,6 +659,7 @@ static int do_dentry_open(struct file *f, | |||
| 654 | if (unlikely(f->f_flags & O_PATH)) | 659 | if (unlikely(f->f_flags & O_PATH)) |
| 655 | f->f_mode = FMODE_PATH; | 660 | f->f_mode = FMODE_PATH; |
| 656 | 661 | ||
| 662 | path_get(&f->f_path); | ||
| 657 | inode = f->f_path.dentry->d_inode; | 663 | inode = f->f_path.dentry->d_inode; |
| 658 | if (f->f_mode & FMODE_WRITE) { | 664 | if (f->f_mode & FMODE_WRITE) { |
| 659 | error = __get_file_write_access(inode, f->f_path.mnt); | 665 | error = __get_file_write_access(inode, f->f_path.mnt); |
| @@ -739,9 +745,7 @@ int finish_open(struct file *file, struct dentry *dentry, | |||
| 739 | int error; | 745 | int error; |
| 740 | BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */ | 746 | BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */ |
| 741 | 747 | ||
| 742 | mntget(file->f_path.mnt); | 748 | file->f_path.dentry = dentry; |
| 743 | file->f_path.dentry = dget(dentry); | ||
| 744 | |||
| 745 | error = do_dentry_open(file, open, current_cred()); | 749 | error = do_dentry_open(file, open, current_cred()); |
| 746 | if (!error) | 750 | if (!error) |
| 747 | *opened |= FILE_OPENED; | 751 | *opened |= FILE_OPENED; |
| @@ -784,7 +788,6 @@ struct file *dentry_open(const struct path *path, int flags, | |||
| 784 | 788 | ||
| 785 | f->f_flags = flags; | 789 | f->f_flags = flags; |
| 786 | f->f_path = *path; | 790 | f->f_path = *path; |
| 787 | path_get(&f->f_path); | ||
| 788 | error = do_dentry_open(f, NULL, cred); | 791 | error = do_dentry_open(f, NULL, cred); |
| 789 | if (!error) { | 792 | if (!error) { |
| 790 | error = open_check_o_direct(f); | 793 | error = open_check_o_direct(f); |
| @@ -1016,18 +1016,16 @@ fail_inode: | |||
| 1016 | return NULL; | 1016 | return NULL; |
| 1017 | } | 1017 | } |
| 1018 | 1018 | ||
| 1019 | struct file *create_write_pipe(int flags) | 1019 | int create_pipe_files(struct file **res, int flags) |
| 1020 | { | 1020 | { |
| 1021 | int err; | 1021 | int err; |
| 1022 | struct inode *inode; | 1022 | struct inode *inode = get_pipe_inode(); |
| 1023 | struct file *f; | 1023 | struct file *f; |
| 1024 | struct path path; | 1024 | struct path path; |
| 1025 | struct qstr name = { .name = "" }; | 1025 | static struct qstr name = { .name = "" }; |
| 1026 | 1026 | ||
| 1027 | err = -ENFILE; | ||
| 1028 | inode = get_pipe_inode(); | ||
| 1029 | if (!inode) | 1027 | if (!inode) |
| 1030 | goto err; | 1028 | return -ENFILE; |
| 1031 | 1029 | ||
| 1032 | err = -ENOMEM; | 1030 | err = -ENOMEM; |
| 1033 | path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &name); | 1031 | path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &name); |
| @@ -1041,62 +1039,43 @@ struct file *create_write_pipe(int flags) | |||
| 1041 | f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops); | 1039 | f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops); |
| 1042 | if (!f) | 1040 | if (!f) |
| 1043 | goto err_dentry; | 1041 | goto err_dentry; |
| 1044 | f->f_mapping = inode->i_mapping; | ||
| 1045 | 1042 | ||
| 1046 | f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); | 1043 | f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); |
| 1047 | f->f_version = 0; | ||
| 1048 | 1044 | ||
| 1049 | return f; | 1045 | res[0] = alloc_file(&path, FMODE_READ, &read_pipefifo_fops); |
| 1046 | if (!res[0]) | ||
| 1047 | goto err_file; | ||
| 1048 | |||
| 1049 | path_get(&path); | ||
| 1050 | res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK); | ||
| 1051 | res[1] = f; | ||
| 1052 | return 0; | ||
| 1050 | 1053 | ||
| 1051 | err_dentry: | 1054 | err_file: |
| 1055 | put_filp(f); | ||
| 1056 | err_dentry: | ||
| 1052 | free_pipe_info(inode); | 1057 | free_pipe_info(inode); |
| 1053 | path_put(&path); | 1058 | path_put(&path); |
| 1054 | return ERR_PTR(err); | 1059 | return err; |
| 1055 | 1060 | ||
| 1056 | err_inode: | 1061 | err_inode: |
| 1057 | free_pipe_info(inode); | 1062 | free_pipe_info(inode); |
| 1058 | iput(inode); | 1063 | iput(inode); |
| 1059 | err: | 1064 | return err; |
| 1060 | return ERR_PTR(err); | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | void free_write_pipe(struct file *f) | ||
| 1064 | { | ||
| 1065 | free_pipe_info(f->f_dentry->d_inode); | ||
| 1066 | path_put(&f->f_path); | ||
| 1067 | put_filp(f); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | struct file *create_read_pipe(struct file *wrf, int flags) | ||
| 1071 | { | ||
| 1072 | /* Grab pipe from the writer */ | ||
| 1073 | struct file *f = alloc_file(&wrf->f_path, FMODE_READ, | ||
| 1074 | &read_pipefifo_fops); | ||
| 1075 | if (!f) | ||
| 1076 | return ERR_PTR(-ENFILE); | ||
| 1077 | |||
| 1078 | path_get(&wrf->f_path); | ||
| 1079 | f->f_flags = O_RDONLY | (flags & O_NONBLOCK); | ||
| 1080 | |||
| 1081 | return f; | ||
| 1082 | } | 1065 | } |
| 1083 | 1066 | ||
| 1084 | int do_pipe_flags(int *fd, int flags) | 1067 | int do_pipe_flags(int *fd, int flags) |
| 1085 | { | 1068 | { |
| 1086 | struct file *fw, *fr; | 1069 | struct file *files[2]; |
| 1087 | int error; | 1070 | int error; |
| 1088 | int fdw, fdr; | 1071 | int fdw, fdr; |
| 1089 | 1072 | ||
| 1090 | if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT)) | 1073 | if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT)) |
| 1091 | return -EINVAL; | 1074 | return -EINVAL; |
| 1092 | 1075 | ||
| 1093 | fw = create_write_pipe(flags); | 1076 | error = create_pipe_files(files, flags); |
| 1094 | if (IS_ERR(fw)) | 1077 | if (error) |
| 1095 | return PTR_ERR(fw); | 1078 | return error; |
| 1096 | fr = create_read_pipe(fw, flags); | ||
| 1097 | error = PTR_ERR(fr); | ||
| 1098 | if (IS_ERR(fr)) | ||
| 1099 | goto err_write_pipe; | ||
| 1100 | 1079 | ||
| 1101 | error = get_unused_fd_flags(flags); | 1080 | error = get_unused_fd_flags(flags); |
| 1102 | if (error < 0) | 1081 | if (error < 0) |
| @@ -1109,8 +1088,8 @@ int do_pipe_flags(int *fd, int flags) | |||
| 1109 | fdw = error; | 1088 | fdw = error; |
| 1110 | 1089 | ||
| 1111 | audit_fd_pair(fdr, fdw); | 1090 | audit_fd_pair(fdr, fdw); |
| 1112 | fd_install(fdr, fr); | 1091 | fd_install(fdr, files[0]); |
| 1113 | fd_install(fdw, fw); | 1092 | fd_install(fdw, files[1]); |
| 1114 | fd[0] = fdr; | 1093 | fd[0] = fdr; |
| 1115 | fd[1] = fdw; | 1094 | fd[1] = fdw; |
| 1116 | 1095 | ||
| @@ -1119,10 +1098,8 @@ int do_pipe_flags(int *fd, int flags) | |||
| 1119 | err_fdr: | 1098 | err_fdr: |
| 1120 | put_unused_fd(fdr); | 1099 | put_unused_fd(fdr); |
| 1121 | err_read_pipe: | 1100 | err_read_pipe: |
| 1122 | path_put(&fr->f_path); | 1101 | fput(files[0]); |
| 1123 | put_filp(fr); | 1102 | fput(files[1]); |
| 1124 | err_write_pipe: | ||
| 1125 | free_write_pipe(fw); | ||
| 1126 | return error; | 1103 | return error; |
| 1127 | } | 1104 | } |
| 1128 | 1105 | ||
diff --git a/fs/splice.c b/fs/splice.c index 7bf08fa22ec9..41514dd89462 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -996,6 +996,8 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
| 996 | }; | 996 | }; |
| 997 | ssize_t ret; | 997 | ssize_t ret; |
| 998 | 998 | ||
| 999 | sb_start_write(inode->i_sb); | ||
| 1000 | |||
| 999 | pipe_lock(pipe); | 1001 | pipe_lock(pipe); |
| 1000 | 1002 | ||
| 1001 | splice_from_pipe_begin(&sd); | 1003 | splice_from_pipe_begin(&sd); |
| @@ -1034,6 +1036,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
| 1034 | *ppos += ret; | 1036 | *ppos += ret; |
| 1035 | balance_dirty_pages_ratelimited_nr(mapping, nr_pages); | 1037 | balance_dirty_pages_ratelimited_nr(mapping, nr_pages); |
| 1036 | } | 1038 | } |
| 1039 | sb_end_write(inode->i_sb); | ||
| 1037 | 1040 | ||
| 1038 | return ret; | 1041 | return ret; |
| 1039 | } | 1042 | } |
diff --git a/fs/super.c b/fs/super.c index 4bf714459a4b..b05cf47463d0 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -33,12 +33,19 @@ | |||
| 33 | #include <linux/rculist_bl.h> | 33 | #include <linux/rculist_bl.h> |
| 34 | #include <linux/cleancache.h> | 34 | #include <linux/cleancache.h> |
| 35 | #include <linux/fsnotify.h> | 35 | #include <linux/fsnotify.h> |
| 36 | #include <linux/lockdep.h> | ||
| 36 | #include "internal.h" | 37 | #include "internal.h" |
| 37 | 38 | ||
| 38 | 39 | ||
| 39 | LIST_HEAD(super_blocks); | 40 | LIST_HEAD(super_blocks); |
| 40 | DEFINE_SPINLOCK(sb_lock); | 41 | DEFINE_SPINLOCK(sb_lock); |
| 41 | 42 | ||
| 43 | static char *sb_writers_name[SB_FREEZE_LEVELS] = { | ||
| 44 | "sb_writers", | ||
| 45 | "sb_pagefaults", | ||
| 46 | "sb_internal", | ||
| 47 | }; | ||
| 48 | |||
| 42 | /* | 49 | /* |
| 43 | * One thing we have to be careful of with a per-sb shrinker is that we don't | 50 | * One thing we have to be careful of with a per-sb shrinker is that we don't |
| 44 | * drop the last active reference to the superblock from within the shrinker. | 51 | * drop the last active reference to the superblock from within the shrinker. |
| @@ -102,6 +109,35 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) | |||
| 102 | return total_objects; | 109 | return total_objects; |
| 103 | } | 110 | } |
| 104 | 111 | ||
| 112 | static int init_sb_writers(struct super_block *s, struct file_system_type *type) | ||
| 113 | { | ||
| 114 | int err; | ||
| 115 | int i; | ||
| 116 | |||
| 117 | for (i = 0; i < SB_FREEZE_LEVELS; i++) { | ||
| 118 | err = percpu_counter_init(&s->s_writers.counter[i], 0); | ||
| 119 | if (err < 0) | ||
| 120 | goto err_out; | ||
| 121 | lockdep_init_map(&s->s_writers.lock_map[i], sb_writers_name[i], | ||
| 122 | &type->s_writers_key[i], 0); | ||
| 123 | } | ||
| 124 | init_waitqueue_head(&s->s_writers.wait); | ||
| 125 | init_waitqueue_head(&s->s_writers.wait_unfrozen); | ||
| 126 | return 0; | ||
| 127 | err_out: | ||
| 128 | while (--i >= 0) | ||
| 129 | percpu_counter_destroy(&s->s_writers.counter[i]); | ||
| 130 | return err; | ||
| 131 | } | ||
| 132 | |||
| 133 | static void destroy_sb_writers(struct super_block *s) | ||
| 134 | { | ||
| 135 | int i; | ||
| 136 | |||
| 137 | for (i = 0; i < SB_FREEZE_LEVELS; i++) | ||
| 138 | percpu_counter_destroy(&s->s_writers.counter[i]); | ||
| 139 | } | ||
| 140 | |||
| 105 | /** | 141 | /** |
| 106 | * alloc_super - create new superblock | 142 | * alloc_super - create new superblock |
| 107 | * @type: filesystem type superblock should belong to | 143 | * @type: filesystem type superblock should belong to |
| @@ -117,18 +153,19 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
| 117 | 153 | ||
| 118 | if (s) { | 154 | if (s) { |
| 119 | if (security_sb_alloc(s)) { | 155 | if (security_sb_alloc(s)) { |
| 156 | /* | ||
| 157 | * We cannot call security_sb_free() without | ||
| 158 | * security_sb_alloc() succeeding. So bail out manually | ||
| 159 | */ | ||
| 120 | kfree(s); | 160 | kfree(s); |
| 121 | s = NULL; | 161 | s = NULL; |
| 122 | goto out; | 162 | goto out; |
| 123 | } | 163 | } |
| 124 | #ifdef CONFIG_SMP | 164 | #ifdef CONFIG_SMP |
| 125 | s->s_files = alloc_percpu(struct list_head); | 165 | s->s_files = alloc_percpu(struct list_head); |
| 126 | if (!s->s_files) { | 166 | if (!s->s_files) |
| 127 | security_sb_free(s); | 167 | goto err_out; |
| 128 | kfree(s); | 168 | else { |
| 129 | s = NULL; | ||
| 130 | goto out; | ||
| 131 | } else { | ||
| 132 | int i; | 169 | int i; |
| 133 | 170 | ||
| 134 | for_each_possible_cpu(i) | 171 | for_each_possible_cpu(i) |
| @@ -137,6 +174,8 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
| 137 | #else | 174 | #else |
| 138 | INIT_LIST_HEAD(&s->s_files); | 175 | INIT_LIST_HEAD(&s->s_files); |
| 139 | #endif | 176 | #endif |
| 177 | if (init_sb_writers(s, type)) | ||
| 178 | goto err_out; | ||
| 140 | s->s_flags = flags; | 179 | s->s_flags = flags; |
| 141 | s->s_bdi = &default_backing_dev_info; | 180 | s->s_bdi = &default_backing_dev_info; |
| 142 | INIT_HLIST_NODE(&s->s_instances); | 181 | INIT_HLIST_NODE(&s->s_instances); |
| @@ -178,7 +217,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
| 178 | mutex_init(&s->s_dquot.dqio_mutex); | 217 | mutex_init(&s->s_dquot.dqio_mutex); |
| 179 | mutex_init(&s->s_dquot.dqonoff_mutex); | 218 | mutex_init(&s->s_dquot.dqonoff_mutex); |
| 180 | init_rwsem(&s->s_dquot.dqptr_sem); | 219 | init_rwsem(&s->s_dquot.dqptr_sem); |
| 181 | init_waitqueue_head(&s->s_wait_unfrozen); | ||
| 182 | s->s_maxbytes = MAX_NON_LFS; | 220 | s->s_maxbytes = MAX_NON_LFS; |
| 183 | s->s_op = &default_op; | 221 | s->s_op = &default_op; |
| 184 | s->s_time_gran = 1000000000; | 222 | s->s_time_gran = 1000000000; |
| @@ -190,6 +228,16 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
| 190 | } | 228 | } |
| 191 | out: | 229 | out: |
| 192 | return s; | 230 | return s; |
| 231 | err_out: | ||
| 232 | security_sb_free(s); | ||
| 233 | #ifdef CONFIG_SMP | ||
| 234 | if (s->s_files) | ||
| 235 | free_percpu(s->s_files); | ||
| 236 | #endif | ||
| 237 | destroy_sb_writers(s); | ||
| 238 | kfree(s); | ||
| 239 | s = NULL; | ||
| 240 | goto out; | ||
| 193 | } | 241 | } |
| 194 | 242 | ||
| 195 | /** | 243 | /** |
| @@ -203,6 +251,7 @@ static inline void destroy_super(struct super_block *s) | |||
| 203 | #ifdef CONFIG_SMP | 251 | #ifdef CONFIG_SMP |
| 204 | free_percpu(s->s_files); | 252 | free_percpu(s->s_files); |
| 205 | #endif | 253 | #endif |
| 254 | destroy_sb_writers(s); | ||
| 206 | security_sb_free(s); | 255 | security_sb_free(s); |
| 207 | WARN_ON(!list_empty(&s->s_mounts)); | 256 | WARN_ON(!list_empty(&s->s_mounts)); |
| 208 | kfree(s->s_subtype); | 257 | kfree(s->s_subtype); |
| @@ -651,10 +700,11 @@ struct super_block *get_super_thawed(struct block_device *bdev) | |||
| 651 | { | 700 | { |
| 652 | while (1) { | 701 | while (1) { |
| 653 | struct super_block *s = get_super(bdev); | 702 | struct super_block *s = get_super(bdev); |
| 654 | if (!s || s->s_frozen == SB_UNFROZEN) | 703 | if (!s || s->s_writers.frozen == SB_UNFROZEN) |
| 655 | return s; | 704 | return s; |
| 656 | up_read(&s->s_umount); | 705 | up_read(&s->s_umount); |
| 657 | vfs_check_frozen(s, SB_FREEZE_WRITE); | 706 | wait_event(s->s_writers.wait_unfrozen, |
| 707 | s->s_writers.frozen == SB_UNFROZEN); | ||
| 658 | put_super(s); | 708 | put_super(s); |
| 659 | } | 709 | } |
| 660 | } | 710 | } |
| @@ -732,7 +782,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
| 732 | int retval; | 782 | int retval; |
| 733 | int remount_ro; | 783 | int remount_ro; |
| 734 | 784 | ||
| 735 | if (sb->s_frozen != SB_UNFROZEN) | 785 | if (sb->s_writers.frozen != SB_UNFROZEN) |
| 736 | return -EBUSY; | 786 | return -EBUSY; |
| 737 | 787 | ||
| 738 | #ifdef CONFIG_BLOCK | 788 | #ifdef CONFIG_BLOCK |
| @@ -1163,6 +1213,120 @@ out: | |||
| 1163 | return ERR_PTR(error); | 1213 | return ERR_PTR(error); |
| 1164 | } | 1214 | } |
| 1165 | 1215 | ||
| 1216 | /* | ||
| 1217 | * This is an internal function, please use sb_end_{write,pagefault,intwrite} | ||
| 1218 | * instead. | ||
| 1219 | */ | ||
| 1220 | void __sb_end_write(struct super_block *sb, int level) | ||
| 1221 | { | ||
| 1222 | percpu_counter_dec(&sb->s_writers.counter[level-1]); | ||
| 1223 | /* | ||
| 1224 | * Make sure s_writers are updated before we wake up waiters in | ||
| 1225 | * freeze_super(). | ||
| 1226 | */ | ||
| 1227 | smp_mb(); | ||
| 1228 | if (waitqueue_active(&sb->s_writers.wait)) | ||
| 1229 | wake_up(&sb->s_writers.wait); | ||
| 1230 | rwsem_release(&sb->s_writers.lock_map[level-1], 1, _RET_IP_); | ||
| 1231 | } | ||
| 1232 | EXPORT_SYMBOL(__sb_end_write); | ||
| 1233 | |||
| 1234 | #ifdef CONFIG_LOCKDEP | ||
| 1235 | /* | ||
| 1236 | * We want lockdep to tell us about possible deadlocks with freezing but | ||
| 1237 | * it's it bit tricky to properly instrument it. Getting a freeze protection | ||
| 1238 | * works as getting a read lock but there are subtle problems. XFS for example | ||
| 1239 | * gets freeze protection on internal level twice in some cases, which is OK | ||
| 1240 | * only because we already hold a freeze protection also on higher level. Due | ||
| 1241 | * to these cases we have to tell lockdep we are doing trylock when we | ||
| 1242 | * already hold a freeze protection for a higher freeze level. | ||
| 1243 | */ | ||
| 1244 | static void acquire_freeze_lock(struct super_block *sb, int level, bool trylock, | ||
| 1245 | unsigned long ip) | ||
| 1246 | { | ||
| 1247 | int i; | ||
| 1248 | |||
| 1249 | if (!trylock) { | ||
| 1250 | for (i = 0; i < level - 1; i++) | ||
| 1251 | if (lock_is_held(&sb->s_writers.lock_map[i])) { | ||
| 1252 | trylock = true; | ||
| 1253 | break; | ||
| 1254 | } | ||
| 1255 | } | ||
| 1256 | rwsem_acquire_read(&sb->s_writers.lock_map[level-1], 0, trylock, ip); | ||
| 1257 | } | ||
| 1258 | #endif | ||
| 1259 | |||
| 1260 | /* | ||
| 1261 | * This is an internal function, please use sb_start_{write,pagefault,intwrite} | ||
| 1262 | * instead. | ||
| 1263 | */ | ||
| 1264 | int __sb_start_write(struct super_block *sb, int level, bool wait) | ||
| 1265 | { | ||
| 1266 | retry: | ||
| 1267 | if (unlikely(sb->s_writers.frozen >= level)) { | ||
| 1268 | if (!wait) | ||
| 1269 | return 0; | ||
| 1270 | wait_event(sb->s_writers.wait_unfrozen, | ||
| 1271 | sb->s_writers.frozen < level); | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | #ifdef CONFIG_LOCKDEP | ||
| 1275 | acquire_freeze_lock(sb, level, !wait, _RET_IP_); | ||
| 1276 | #endif | ||
| 1277 | percpu_counter_inc(&sb->s_writers.counter[level-1]); | ||
| 1278 | /* | ||
| 1279 | * Make sure counter is updated before we check for frozen. | ||
| 1280 | * freeze_super() first sets frozen and then checks the counter. | ||
| 1281 | */ | ||
| 1282 | smp_mb(); | ||
| 1283 | if (unlikely(sb->s_writers.frozen >= level)) { | ||
| 1284 | __sb_end_write(sb, level); | ||
| 1285 | goto retry; | ||
| 1286 | } | ||
| 1287 | return 1; | ||
| 1288 | } | ||
| 1289 | EXPORT_SYMBOL(__sb_start_write); | ||
| 1290 | |||
| 1291 | /** | ||
| 1292 | * sb_wait_write - wait until all writers to given file system finish | ||
| 1293 | * @sb: the super for which we wait | ||
| 1294 | * @level: type of writers we wait for (normal vs page fault) | ||
| 1295 | * | ||
| 1296 | * This function waits until there are no writers of given type to given file | ||
| 1297 | * system. Caller of this function should make sure there can be no new writers | ||
| 1298 | * of type @level before calling this function. Otherwise this function can | ||
| 1299 | * livelock. | ||
| 1300 | */ | ||
| 1301 | static void sb_wait_write(struct super_block *sb, int level) | ||
| 1302 | { | ||
| 1303 | s64 writers; | ||
| 1304 | |||
| 1305 | /* | ||
| 1306 | * We just cycle-through lockdep here so that it does not complain | ||
| 1307 | * about returning with lock to userspace | ||
| 1308 | */ | ||
| 1309 | rwsem_acquire(&sb->s_writers.lock_map[level-1], 0, 0, _THIS_IP_); | ||
| 1310 | rwsem_release(&sb->s_writers.lock_map[level-1], 1, _THIS_IP_); | ||
| 1311 | |||
| 1312 | do { | ||
| 1313 | DEFINE_WAIT(wait); | ||
| 1314 | |||
| 1315 | /* | ||
| 1316 | * We use a barrier in prepare_to_wait() to separate setting | ||
| 1317 | * of frozen and checking of the counter | ||
| 1318 | */ | ||
| 1319 | prepare_to_wait(&sb->s_writers.wait, &wait, | ||
| 1320 | TASK_UNINTERRUPTIBLE); | ||
| 1321 | |||
| 1322 | writers = percpu_counter_sum(&sb->s_writers.counter[level-1]); | ||
| 1323 | if (writers) | ||
| 1324 | schedule(); | ||
| 1325 | |||
| 1326 | finish_wait(&sb->s_writers.wait, &wait); | ||
| 1327 | } while (writers); | ||
| 1328 | } | ||
| 1329 | |||
| 1166 | /** | 1330 | /** |
| 1167 | * freeze_super - lock the filesystem and force it into a consistent state | 1331 | * freeze_super - lock the filesystem and force it into a consistent state |
| 1168 | * @sb: the super to lock | 1332 | * @sb: the super to lock |
| @@ -1170,6 +1334,31 @@ out: | |||
| 1170 | * Syncs the super to make sure the filesystem is consistent and calls the fs's | 1334 | * Syncs the super to make sure the filesystem is consistent and calls the fs's |
| 1171 | * freeze_fs. Subsequent calls to this without first thawing the fs will return | 1335 | * freeze_fs. Subsequent calls to this without first thawing the fs will return |
| 1172 | * -EBUSY. | 1336 | * -EBUSY. |
| 1337 | * | ||
| 1338 | * During this function, sb->s_writers.frozen goes through these values: | ||
| 1339 | * | ||
| 1340 | * SB_UNFROZEN: File system is normal, all writes progress as usual. | ||
| 1341 | * | ||
| 1342 | * SB_FREEZE_WRITE: The file system is in the process of being frozen. New | ||
| 1343 | * writes should be blocked, though page faults are still allowed. We wait for | ||
| 1344 | * all writes to complete and then proceed to the next stage. | ||
| 1345 | * | ||
| 1346 | * SB_FREEZE_PAGEFAULT: Freezing continues. Now also page faults are blocked | ||
| 1347 | * but internal fs threads can still modify the filesystem (although they | ||
| 1348 | * should not dirty new pages or inodes), writeback can run etc. After waiting | ||
| 1349 | * for all running page faults we sync the filesystem which will clean all | ||
| 1350 | * dirty pages and inodes (no new dirty pages or inodes can be created when | ||
| 1351 | * sync is running). | ||
| 1352 | * | ||
| 1353 | * SB_FREEZE_FS: The file system is frozen. Now all internal sources of fs | ||
| 1354 | * modification are blocked (e.g. XFS preallocation truncation on inode | ||
| 1355 | * reclaim). This is usually implemented by blocking new transactions for | ||
| 1356 | * filesystems that have them and need this additional guard. After all | ||
| 1357 | * internal writers are finished we call ->freeze_fs() to finish filesystem | ||
| 1358 | * freezing. Then we transition to SB_FREEZE_COMPLETE state. This state is | ||
| 1359 | * mostly auxiliary for filesystems to verify they do not modify frozen fs. | ||
| 1360 | * | ||
| 1361 | * sb->s_writers.frozen is protected by sb->s_umount. | ||
| 1173 | */ | 1362 | */ |
| 1174 | int freeze_super(struct super_block *sb) | 1363 | int freeze_super(struct super_block *sb) |
| 1175 | { | 1364 | { |
| @@ -1177,7 +1366,7 @@ int freeze_super(struct super_block *sb) | |||
| 1177 | 1366 | ||
| 1178 | atomic_inc(&sb->s_active); | 1367 | atomic_inc(&sb->s_active); |
| 1179 | down_write(&sb->s_umount); | 1368 | down_write(&sb->s_umount); |
| 1180 | if (sb->s_frozen) { | 1369 | if (sb->s_writers.frozen != SB_UNFROZEN) { |
| 1181 | deactivate_locked_super(sb); | 1370 | deactivate_locked_super(sb); |
| 1182 | return -EBUSY; | 1371 | return -EBUSY; |
| 1183 | } | 1372 | } |
| @@ -1188,33 +1377,53 @@ int freeze_super(struct super_block *sb) | |||
| 1188 | } | 1377 | } |
| 1189 | 1378 | ||
| 1190 | if (sb->s_flags & MS_RDONLY) { | 1379 | if (sb->s_flags & MS_RDONLY) { |
| 1191 | sb->s_frozen = SB_FREEZE_TRANS; | 1380 | /* Nothing to do really... */ |
| 1192 | smp_wmb(); | 1381 | sb->s_writers.frozen = SB_FREEZE_COMPLETE; |
| 1193 | up_write(&sb->s_umount); | 1382 | up_write(&sb->s_umount); |
| 1194 | return 0; | 1383 | return 0; |
| 1195 | } | 1384 | } |
| 1196 | 1385 | ||
| 1197 | sb->s_frozen = SB_FREEZE_WRITE; | 1386 | /* From now on, no new normal writers can start */ |
| 1387 | sb->s_writers.frozen = SB_FREEZE_WRITE; | ||
| 1388 | smp_wmb(); | ||
| 1389 | |||
| 1390 | /* Release s_umount to preserve sb_start_write -> s_umount ordering */ | ||
| 1391 | up_write(&sb->s_umount); | ||
| 1392 | |||
| 1393 | sb_wait_write(sb, SB_FREEZE_WRITE); | ||
| 1394 | |||
| 1395 | /* Now we go and block page faults... */ | ||
| 1396 | down_write(&sb->s_umount); | ||
| 1397 | sb->s_writers.frozen = SB_FREEZE_PAGEFAULT; | ||
| 1198 | smp_wmb(); | 1398 | smp_wmb(); |
| 1199 | 1399 | ||
| 1400 | sb_wait_write(sb, SB_FREEZE_PAGEFAULT); | ||
| 1401 | |||
| 1402 | /* All writers are done so after syncing there won't be dirty data */ | ||
| 1200 | sync_filesystem(sb); | 1403 | sync_filesystem(sb); |
| 1201 | 1404 | ||
| 1202 | sb->s_frozen = SB_FREEZE_TRANS; | 1405 | /* Now wait for internal filesystem counter */ |
| 1406 | sb->s_writers.frozen = SB_FREEZE_FS; | ||
| 1203 | smp_wmb(); | 1407 | smp_wmb(); |
| 1408 | sb_wait_write(sb, SB_FREEZE_FS); | ||
| 1204 | 1409 | ||
| 1205 | sync_blockdev(sb->s_bdev); | ||
| 1206 | if (sb->s_op->freeze_fs) { | 1410 | if (sb->s_op->freeze_fs) { |
| 1207 | ret = sb->s_op->freeze_fs(sb); | 1411 | ret = sb->s_op->freeze_fs(sb); |
| 1208 | if (ret) { | 1412 | if (ret) { |
| 1209 | printk(KERN_ERR | 1413 | printk(KERN_ERR |
| 1210 | "VFS:Filesystem freeze failed\n"); | 1414 | "VFS:Filesystem freeze failed\n"); |
| 1211 | sb->s_frozen = SB_UNFROZEN; | 1415 | sb->s_writers.frozen = SB_UNFROZEN; |
| 1212 | smp_wmb(); | 1416 | smp_wmb(); |
| 1213 | wake_up(&sb->s_wait_unfrozen); | 1417 | wake_up(&sb->s_writers.wait_unfrozen); |
| 1214 | deactivate_locked_super(sb); | 1418 | deactivate_locked_super(sb); |
| 1215 | return ret; | 1419 | return ret; |
| 1216 | } | 1420 | } |
| 1217 | } | 1421 | } |
| 1422 | /* | ||
| 1423 | * This is just for debugging purposes so that fs can warn if it | ||
| 1424 | * sees write activity when frozen is set to SB_FREEZE_COMPLETE. | ||
| 1425 | */ | ||
| 1426 | sb->s_writers.frozen = SB_FREEZE_COMPLETE; | ||
| 1218 | up_write(&sb->s_umount); | 1427 | up_write(&sb->s_umount); |
| 1219 | return 0; | 1428 | return 0; |
| 1220 | } | 1429 | } |
| @@ -1231,7 +1440,7 @@ int thaw_super(struct super_block *sb) | |||
| 1231 | int error; | 1440 | int error; |
| 1232 | 1441 | ||
| 1233 | down_write(&sb->s_umount); | 1442 | down_write(&sb->s_umount); |
| 1234 | if (sb->s_frozen == SB_UNFROZEN) { | 1443 | if (sb->s_writers.frozen == SB_UNFROZEN) { |
| 1235 | up_write(&sb->s_umount); | 1444 | up_write(&sb->s_umount); |
| 1236 | return -EINVAL; | 1445 | return -EINVAL; |
| 1237 | } | 1446 | } |
| @@ -1244,16 +1453,15 @@ int thaw_super(struct super_block *sb) | |||
| 1244 | if (error) { | 1453 | if (error) { |
| 1245 | printk(KERN_ERR | 1454 | printk(KERN_ERR |
| 1246 | "VFS:Filesystem thaw failed\n"); | 1455 | "VFS:Filesystem thaw failed\n"); |
| 1247 | sb->s_frozen = SB_FREEZE_TRANS; | ||
| 1248 | up_write(&sb->s_umount); | 1456 | up_write(&sb->s_umount); |
| 1249 | return error; | 1457 | return error; |
| 1250 | } | 1458 | } |
| 1251 | } | 1459 | } |
| 1252 | 1460 | ||
| 1253 | out: | 1461 | out: |
| 1254 | sb->s_frozen = SB_UNFROZEN; | 1462 | sb->s_writers.frozen = SB_UNFROZEN; |
| 1255 | smp_wmb(); | 1463 | smp_wmb(); |
| 1256 | wake_up(&sb->s_wait_unfrozen); | 1464 | wake_up(&sb->s_writers.wait_unfrozen); |
| 1257 | deactivate_locked_super(sb); | 1465 | deactivate_locked_super(sb); |
| 1258 | 1466 | ||
| 1259 | return 0; | 1467 | return 0; |
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index a4759833d62d..614b2b544880 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
| @@ -228,6 +228,8 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 228 | ret = 0; | 228 | ret = 0; |
| 229 | if (bb->vm_ops->page_mkwrite) | 229 | if (bb->vm_ops->page_mkwrite) |
| 230 | ret = bb->vm_ops->page_mkwrite(vma, vmf); | 230 | ret = bb->vm_ops->page_mkwrite(vma, vmf); |
| 231 | else | ||
| 232 | file_update_time(file); | ||
| 231 | 233 | ||
| 232 | sysfs_put_active(attr_sd); | 234 | sysfs_put_active(attr_sd); |
| 233 | return ret; | 235 | return ret; |
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 15052ff916ec..e562dd43f41f 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
| @@ -124,6 +124,12 @@ xfs_setfilesize_trans_alloc( | |||
| 124 | ioend->io_append_trans = tp; | 124 | ioend->io_append_trans = tp; |
| 125 | 125 | ||
| 126 | /* | 126 | /* |
| 127 | * We will pass freeze protection with a transaction. So tell lockdep | ||
| 128 | * we released it. | ||
| 129 | */ | ||
| 130 | rwsem_release(&ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], | ||
| 131 | 1, _THIS_IP_); | ||
| 132 | /* | ||
| 127 | * We hand off the transaction to the completion thread now, so | 133 | * We hand off the transaction to the completion thread now, so |
| 128 | * clear the flag here. | 134 | * clear the flag here. |
| 129 | */ | 135 | */ |
| @@ -199,6 +205,15 @@ xfs_end_io( | |||
| 199 | struct xfs_inode *ip = XFS_I(ioend->io_inode); | 205 | struct xfs_inode *ip = XFS_I(ioend->io_inode); |
| 200 | int error = 0; | 206 | int error = 0; |
| 201 | 207 | ||
| 208 | if (ioend->io_append_trans) { | ||
| 209 | /* | ||
| 210 | * We've got freeze protection passed with the transaction. | ||
| 211 | * Tell lockdep about it. | ||
| 212 | */ | ||
| 213 | rwsem_acquire_read( | ||
| 214 | &ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], | ||
| 215 | 0, 1, _THIS_IP_); | ||
| 216 | } | ||
| 202 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 217 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
| 203 | ioend->io_error = -EIO; | 218 | ioend->io_error = -EIO; |
| 204 | goto done; | 219 | goto done; |
| @@ -1425,6 +1440,9 @@ out_trans_cancel: | |||
| 1425 | if (ioend->io_append_trans) { | 1440 | if (ioend->io_append_trans) { |
| 1426 | current_set_flags_nested(&ioend->io_append_trans->t_pflags, | 1441 | current_set_flags_nested(&ioend->io_append_trans->t_pflags, |
| 1427 | PF_FSTRANS); | 1442 | PF_FSTRANS); |
| 1443 | rwsem_acquire_read( | ||
| 1444 | &inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], | ||
| 1445 | 0, 1, _THIS_IP_); | ||
| 1428 | xfs_trans_cancel(ioend->io_append_trans, 0); | 1446 | xfs_trans_cancel(ioend->io_append_trans, 0); |
| 1429 | } | 1447 | } |
| 1430 | out_destroy_ioend: | 1448 | out_destroy_ioend: |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index c4559c6e6f2c..56afcdb2377d 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -770,10 +770,12 @@ xfs_file_aio_write( | |||
| 770 | if (ocount == 0) | 770 | if (ocount == 0) |
| 771 | return 0; | 771 | return 0; |
| 772 | 772 | ||
| 773 | xfs_wait_for_freeze(ip->i_mount, SB_FREEZE_WRITE); | 773 | sb_start_write(inode->i_sb); |
| 774 | 774 | ||
| 775 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 775 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
| 776 | return -EIO; | 776 | ret = -EIO; |
| 777 | goto out; | ||
| 778 | } | ||
| 777 | 779 | ||
| 778 | if (unlikely(file->f_flags & O_DIRECT)) | 780 | if (unlikely(file->f_flags & O_DIRECT)) |
| 779 | ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount); | 781 | ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount); |
| @@ -792,6 +794,8 @@ xfs_file_aio_write( | |||
| 792 | ret = err; | 794 | ret = err; |
| 793 | } | 795 | } |
| 794 | 796 | ||
| 797 | out: | ||
| 798 | sb_end_write(inode->i_sb); | ||
| 795 | return ret; | 799 | return ret; |
| 796 | } | 800 | } |
| 797 | 801 | ||
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 1f1535d25a9b..0e0232c3b6d9 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
| @@ -364,9 +364,15 @@ xfs_fssetdm_by_handle( | |||
| 364 | if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t))) | 364 | if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t))) |
| 365 | return -XFS_ERROR(EFAULT); | 365 | return -XFS_ERROR(EFAULT); |
| 366 | 366 | ||
| 367 | error = mnt_want_write_file(parfilp); | ||
| 368 | if (error) | ||
| 369 | return error; | ||
| 370 | |||
| 367 | dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq); | 371 | dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq); |
| 368 | if (IS_ERR(dentry)) | 372 | if (IS_ERR(dentry)) { |
| 373 | mnt_drop_write_file(parfilp); | ||
| 369 | return PTR_ERR(dentry); | 374 | return PTR_ERR(dentry); |
| 375 | } | ||
| 370 | 376 | ||
| 371 | if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) { | 377 | if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) { |
| 372 | error = -XFS_ERROR(EPERM); | 378 | error = -XFS_ERROR(EPERM); |
| @@ -382,6 +388,7 @@ xfs_fssetdm_by_handle( | |||
| 382 | fsd.fsd_dmstate); | 388 | fsd.fsd_dmstate); |
| 383 | 389 | ||
| 384 | out: | 390 | out: |
| 391 | mnt_drop_write_file(parfilp); | ||
| 385 | dput(dentry); | 392 | dput(dentry); |
| 386 | return error; | 393 | return error; |
| 387 | } | 394 | } |
| @@ -634,7 +641,11 @@ xfs_ioc_space( | |||
| 634 | if (ioflags & IO_INVIS) | 641 | if (ioflags & IO_INVIS) |
| 635 | attr_flags |= XFS_ATTR_DMI; | 642 | attr_flags |= XFS_ATTR_DMI; |
| 636 | 643 | ||
| 644 | error = mnt_want_write_file(filp); | ||
| 645 | if (error) | ||
| 646 | return error; | ||
| 637 | error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); | 647 | error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); |
| 648 | mnt_drop_write_file(filp); | ||
| 638 | return -error; | 649 | return -error; |
| 639 | } | 650 | } |
| 640 | 651 | ||
| @@ -1163,6 +1174,7 @@ xfs_ioc_fssetxattr( | |||
| 1163 | { | 1174 | { |
| 1164 | struct fsxattr fa; | 1175 | struct fsxattr fa; |
| 1165 | unsigned int mask; | 1176 | unsigned int mask; |
| 1177 | int error; | ||
| 1166 | 1178 | ||
| 1167 | if (copy_from_user(&fa, arg, sizeof(fa))) | 1179 | if (copy_from_user(&fa, arg, sizeof(fa))) |
| 1168 | return -EFAULT; | 1180 | return -EFAULT; |
| @@ -1171,7 +1183,12 @@ xfs_ioc_fssetxattr( | |||
| 1171 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) | 1183 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) |
| 1172 | mask |= FSX_NONBLOCK; | 1184 | mask |= FSX_NONBLOCK; |
| 1173 | 1185 | ||
| 1174 | return -xfs_ioctl_setattr(ip, &fa, mask); | 1186 | error = mnt_want_write_file(filp); |
| 1187 | if (error) | ||
| 1188 | return error; | ||
| 1189 | error = xfs_ioctl_setattr(ip, &fa, mask); | ||
| 1190 | mnt_drop_write_file(filp); | ||
| 1191 | return -error; | ||
| 1175 | } | 1192 | } |
| 1176 | 1193 | ||
| 1177 | STATIC int | 1194 | STATIC int |
| @@ -1196,6 +1213,7 @@ xfs_ioc_setxflags( | |||
| 1196 | struct fsxattr fa; | 1213 | struct fsxattr fa; |
| 1197 | unsigned int flags; | 1214 | unsigned int flags; |
| 1198 | unsigned int mask; | 1215 | unsigned int mask; |
| 1216 | int error; | ||
| 1199 | 1217 | ||
| 1200 | if (copy_from_user(&flags, arg, sizeof(flags))) | 1218 | if (copy_from_user(&flags, arg, sizeof(flags))) |
| 1201 | return -EFAULT; | 1219 | return -EFAULT; |
| @@ -1210,7 +1228,12 @@ xfs_ioc_setxflags( | |||
| 1210 | mask |= FSX_NONBLOCK; | 1228 | mask |= FSX_NONBLOCK; |
| 1211 | fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); | 1229 | fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); |
| 1212 | 1230 | ||
| 1213 | return -xfs_ioctl_setattr(ip, &fa, mask); | 1231 | error = mnt_want_write_file(filp); |
| 1232 | if (error) | ||
| 1233 | return error; | ||
| 1234 | error = xfs_ioctl_setattr(ip, &fa, mask); | ||
| 1235 | mnt_drop_write_file(filp); | ||
| 1236 | return -error; | ||
| 1214 | } | 1237 | } |
| 1215 | 1238 | ||
| 1216 | STATIC int | 1239 | STATIC int |
| @@ -1385,8 +1408,13 @@ xfs_file_ioctl( | |||
| 1385 | if (copy_from_user(&dmi, arg, sizeof(dmi))) | 1408 | if (copy_from_user(&dmi, arg, sizeof(dmi))) |
| 1386 | return -XFS_ERROR(EFAULT); | 1409 | return -XFS_ERROR(EFAULT); |
| 1387 | 1410 | ||
| 1411 | error = mnt_want_write_file(filp); | ||
| 1412 | if (error) | ||
| 1413 | return error; | ||
| 1414 | |||
| 1388 | error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, | 1415 | error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, |
| 1389 | dmi.fsd_dmstate); | 1416 | dmi.fsd_dmstate); |
| 1417 | mnt_drop_write_file(filp); | ||
| 1390 | return -error; | 1418 | return -error; |
| 1391 | } | 1419 | } |
| 1392 | 1420 | ||
| @@ -1434,7 +1462,11 @@ xfs_file_ioctl( | |||
| 1434 | 1462 | ||
| 1435 | if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t))) | 1463 | if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t))) |
| 1436 | return -XFS_ERROR(EFAULT); | 1464 | return -XFS_ERROR(EFAULT); |
| 1465 | error = mnt_want_write_file(filp); | ||
| 1466 | if (error) | ||
| 1467 | return error; | ||
| 1437 | error = xfs_swapext(&sxp); | 1468 | error = xfs_swapext(&sxp); |
| 1469 | mnt_drop_write_file(filp); | ||
| 1438 | return -error; | 1470 | return -error; |
| 1439 | } | 1471 | } |
| 1440 | 1472 | ||
| @@ -1463,9 +1495,14 @@ xfs_file_ioctl( | |||
| 1463 | if (copy_from_user(&inout, arg, sizeof(inout))) | 1495 | if (copy_from_user(&inout, arg, sizeof(inout))) |
| 1464 | return -XFS_ERROR(EFAULT); | 1496 | return -XFS_ERROR(EFAULT); |
| 1465 | 1497 | ||
| 1498 | error = mnt_want_write_file(filp); | ||
| 1499 | if (error) | ||
| 1500 | return error; | ||
| 1501 | |||
| 1466 | /* input parameter is passed in resblks field of structure */ | 1502 | /* input parameter is passed in resblks field of structure */ |
| 1467 | in = inout.resblks; | 1503 | in = inout.resblks; |
| 1468 | error = xfs_reserve_blocks(mp, &in, &inout); | 1504 | error = xfs_reserve_blocks(mp, &in, &inout); |
| 1505 | mnt_drop_write_file(filp); | ||
| 1469 | if (error) | 1506 | if (error) |
| 1470 | return -error; | 1507 | return -error; |
| 1471 | 1508 | ||
| @@ -1496,7 +1533,11 @@ xfs_file_ioctl( | |||
| 1496 | if (copy_from_user(&in, arg, sizeof(in))) | 1533 | if (copy_from_user(&in, arg, sizeof(in))) |
| 1497 | return -XFS_ERROR(EFAULT); | 1534 | return -XFS_ERROR(EFAULT); |
| 1498 | 1535 | ||
| 1536 | error = mnt_want_write_file(filp); | ||
| 1537 | if (error) | ||
| 1538 | return error; | ||
| 1499 | error = xfs_growfs_data(mp, &in); | 1539 | error = xfs_growfs_data(mp, &in); |
| 1540 | mnt_drop_write_file(filp); | ||
| 1500 | return -error; | 1541 | return -error; |
| 1501 | } | 1542 | } |
| 1502 | 1543 | ||
| @@ -1506,7 +1547,11 @@ xfs_file_ioctl( | |||
| 1506 | if (copy_from_user(&in, arg, sizeof(in))) | 1547 | if (copy_from_user(&in, arg, sizeof(in))) |
| 1507 | return -XFS_ERROR(EFAULT); | 1548 | return -XFS_ERROR(EFAULT); |
| 1508 | 1549 | ||
| 1550 | error = mnt_want_write_file(filp); | ||
| 1551 | if (error) | ||
| 1552 | return error; | ||
| 1509 | error = xfs_growfs_log(mp, &in); | 1553 | error = xfs_growfs_log(mp, &in); |
| 1554 | mnt_drop_write_file(filp); | ||
| 1510 | return -error; | 1555 | return -error; |
| 1511 | } | 1556 | } |
| 1512 | 1557 | ||
| @@ -1516,7 +1561,11 @@ xfs_file_ioctl( | |||
| 1516 | if (copy_from_user(&in, arg, sizeof(in))) | 1561 | if (copy_from_user(&in, arg, sizeof(in))) |
| 1517 | return -XFS_ERROR(EFAULT); | 1562 | return -XFS_ERROR(EFAULT); |
| 1518 | 1563 | ||
| 1564 | error = mnt_want_write_file(filp); | ||
| 1565 | if (error) | ||
| 1566 | return error; | ||
| 1519 | error = xfs_growfs_rt(mp, &in); | 1567 | error = xfs_growfs_rt(mp, &in); |
| 1568 | mnt_drop_write_file(filp); | ||
| 1520 | return -error; | 1569 | return -error; |
| 1521 | } | 1570 | } |
| 1522 | 1571 | ||
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index c4f2da0d2bf5..1244274a5674 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c | |||
| @@ -600,7 +600,11 @@ xfs_file_compat_ioctl( | |||
| 600 | 600 | ||
| 601 | if (xfs_compat_growfs_data_copyin(&in, arg)) | 601 | if (xfs_compat_growfs_data_copyin(&in, arg)) |
| 602 | return -XFS_ERROR(EFAULT); | 602 | return -XFS_ERROR(EFAULT); |
| 603 | error = mnt_want_write_file(filp); | ||
| 604 | if (error) | ||
| 605 | return error; | ||
| 603 | error = xfs_growfs_data(mp, &in); | 606 | error = xfs_growfs_data(mp, &in); |
| 607 | mnt_drop_write_file(filp); | ||
| 604 | return -error; | 608 | return -error; |
| 605 | } | 609 | } |
| 606 | case XFS_IOC_FSGROWFSRT_32: { | 610 | case XFS_IOC_FSGROWFSRT_32: { |
| @@ -608,7 +612,11 @@ xfs_file_compat_ioctl( | |||
| 608 | 612 | ||
| 609 | if (xfs_compat_growfs_rt_copyin(&in, arg)) | 613 | if (xfs_compat_growfs_rt_copyin(&in, arg)) |
| 610 | return -XFS_ERROR(EFAULT); | 614 | return -XFS_ERROR(EFAULT); |
| 615 | error = mnt_want_write_file(filp); | ||
| 616 | if (error) | ||
| 617 | return error; | ||
| 611 | error = xfs_growfs_rt(mp, &in); | 618 | error = xfs_growfs_rt(mp, &in); |
| 619 | mnt_drop_write_file(filp); | ||
| 612 | return -error; | 620 | return -error; |
| 613 | } | 621 | } |
| 614 | #endif | 622 | #endif |
| @@ -627,7 +635,11 @@ xfs_file_compat_ioctl( | |||
| 627 | offsetof(struct xfs_swapext, sx_stat)) || | 635 | offsetof(struct xfs_swapext, sx_stat)) || |
| 628 | xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat)) | 636 | xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat)) |
| 629 | return -XFS_ERROR(EFAULT); | 637 | return -XFS_ERROR(EFAULT); |
| 638 | error = mnt_want_write_file(filp); | ||
| 639 | if (error) | ||
| 640 | return error; | ||
| 630 | error = xfs_swapext(&sxp); | 641 | error = xfs_swapext(&sxp); |
| 642 | mnt_drop_write_file(filp); | ||
| 631 | return -error; | 643 | return -error; |
| 632 | } | 644 | } |
| 633 | case XFS_IOC_FSBULKSTAT_32: | 645 | case XFS_IOC_FSBULKSTAT_32: |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 915edf6639f0..973dff6ad935 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
| @@ -680,9 +680,9 @@ xfs_iomap_write_unwritten( | |||
| 680 | * the same inode that we complete here and might deadlock | 680 | * the same inode that we complete here and might deadlock |
| 681 | * on the iolock. | 681 | * on the iolock. |
| 682 | */ | 682 | */ |
| 683 | xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); | 683 | sb_start_intwrite(mp->m_super); |
| 684 | tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS); | 684 | tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS); |
| 685 | tp->t_flags |= XFS_TRANS_RESERVE; | 685 | tp->t_flags |= XFS_TRANS_RESERVE | XFS_TRANS_FREEZE_PROT; |
| 686 | error = xfs_trans_reserve(tp, resblks, | 686 | error = xfs_trans_reserve(tp, resblks, |
| 687 | XFS_WRITE_LOG_RES(mp), 0, | 687 | XFS_WRITE_LOG_RES(mp), 0, |
| 688 | XFS_TRANS_PERM_LOG_RES, | 688 | XFS_TRANS_PERM_LOG_RES, |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 711ca51ca3d7..29c2f83d4147 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
| @@ -1551,7 +1551,7 @@ xfs_unmountfs( | |||
| 1551 | int | 1551 | int |
| 1552 | xfs_fs_writable(xfs_mount_t *mp) | 1552 | xfs_fs_writable(xfs_mount_t *mp) |
| 1553 | { | 1553 | { |
| 1554 | return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) || | 1554 | return !(mp->m_super->s_writers.frozen || XFS_FORCED_SHUTDOWN(mp) || |
| 1555 | (mp->m_flags & XFS_MOUNT_RDONLY)); | 1555 | (mp->m_flags & XFS_MOUNT_RDONLY)); |
| 1556 | } | 1556 | } |
| 1557 | 1557 | ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 8724336a9a08..05a05a7b6119 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
| @@ -311,9 +311,6 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname, | |||
| 311 | #define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ | 311 | #define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ |
| 312 | #define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ | 312 | #define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ |
| 313 | 313 | ||
| 314 | #define xfs_test_for_freeze(mp) ((mp)->m_super->s_frozen) | ||
| 315 | #define xfs_wait_for_freeze(mp,l) vfs_check_frozen((mp)->m_super, (l)) | ||
| 316 | |||
| 317 | /* | 314 | /* |
| 318 | * Flags for xfs_mountfs | 315 | * Flags for xfs_mountfs |
| 319 | */ | 316 | */ |
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index 97304f10e78a..96548176db80 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c | |||
| @@ -403,7 +403,7 @@ xfs_sync_worker( | |||
| 403 | if (!(mp->m_super->s_flags & MS_ACTIVE) && | 403 | if (!(mp->m_super->s_flags & MS_ACTIVE) && |
| 404 | !(mp->m_flags & XFS_MOUNT_RDONLY)) { | 404 | !(mp->m_flags & XFS_MOUNT_RDONLY)) { |
| 405 | /* dgc: errors ignored here */ | 405 | /* dgc: errors ignored here */ |
| 406 | if (mp->m_super->s_frozen == SB_UNFROZEN && | 406 | if (mp->m_super->s_writers.frozen == SB_UNFROZEN && |
| 407 | xfs_log_need_covered(mp)) | 407 | xfs_log_need_covered(mp)) |
| 408 | error = xfs_fs_log_dummy(mp); | 408 | error = xfs_fs_log_dummy(mp); |
| 409 | else | 409 | else |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index fdf324508c5e..06ed520a767f 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
| @@ -576,8 +576,12 @@ xfs_trans_alloc( | |||
| 576 | xfs_mount_t *mp, | 576 | xfs_mount_t *mp, |
| 577 | uint type) | 577 | uint type) |
| 578 | { | 578 | { |
| 579 | xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); | 579 | xfs_trans_t *tp; |
| 580 | return _xfs_trans_alloc(mp, type, KM_SLEEP); | 580 | |
| 581 | sb_start_intwrite(mp->m_super); | ||
| 582 | tp = _xfs_trans_alloc(mp, type, KM_SLEEP); | ||
| 583 | tp->t_flags |= XFS_TRANS_FREEZE_PROT; | ||
| 584 | return tp; | ||
| 581 | } | 585 | } |
| 582 | 586 | ||
| 583 | xfs_trans_t * | 587 | xfs_trans_t * |
| @@ -588,6 +592,7 @@ _xfs_trans_alloc( | |||
| 588 | { | 592 | { |
| 589 | xfs_trans_t *tp; | 593 | xfs_trans_t *tp; |
| 590 | 594 | ||
| 595 | WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); | ||
| 591 | atomic_inc(&mp->m_active_trans); | 596 | atomic_inc(&mp->m_active_trans); |
| 592 | 597 | ||
| 593 | tp = kmem_zone_zalloc(xfs_trans_zone, memflags); | 598 | tp = kmem_zone_zalloc(xfs_trans_zone, memflags); |
| @@ -611,6 +616,8 @@ xfs_trans_free( | |||
| 611 | xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false); | 616 | xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false); |
| 612 | 617 | ||
| 613 | atomic_dec(&tp->t_mountp->m_active_trans); | 618 | atomic_dec(&tp->t_mountp->m_active_trans); |
| 619 | if (tp->t_flags & XFS_TRANS_FREEZE_PROT) | ||
| 620 | sb_end_intwrite(tp->t_mountp->m_super); | ||
| 614 | xfs_trans_free_dqinfo(tp); | 621 | xfs_trans_free_dqinfo(tp); |
| 615 | kmem_zone_free(xfs_trans_zone, tp); | 622 | kmem_zone_free(xfs_trans_zone, tp); |
| 616 | } | 623 | } |
| @@ -643,7 +650,11 @@ xfs_trans_dup( | |||
| 643 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | 650 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); |
| 644 | ASSERT(tp->t_ticket != NULL); | 651 | ASSERT(tp->t_ticket != NULL); |
| 645 | 652 | ||
| 646 | ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE); | 653 | ntp->t_flags = XFS_TRANS_PERM_LOG_RES | |
| 654 | (tp->t_flags & XFS_TRANS_RESERVE) | | ||
| 655 | (tp->t_flags & XFS_TRANS_FREEZE_PROT); | ||
| 656 | /* We gave our writer reference to the new transaction */ | ||
| 657 | tp->t_flags &= ~XFS_TRANS_FREEZE_PROT; | ||
| 647 | ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket); | 658 | ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket); |
| 648 | ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used; | 659 | ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used; |
| 649 | tp->t_blk_res = tp->t_blk_res_used; | 660 | tp->t_blk_res = tp->t_blk_res_used; |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index bc2afd52a0b7..db056544cbb5 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
| @@ -179,6 +179,8 @@ struct xfs_log_item_desc { | |||
| 179 | #define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ | 179 | #define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ |
| 180 | #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ | 180 | #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ |
| 181 | #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ | 181 | #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ |
| 182 | #define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer | ||
| 183 | count in superblock */ | ||
| 182 | 184 | ||
| 183 | /* | 185 | /* |
| 184 | * Values for call flags parameter. | 186 | * Values for call flags parameter. |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 22f292a917a3..36abf2aa7e68 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -130,6 +130,7 @@ | |||
| 130 | #define AUDIT_LAST_KERN_ANOM_MSG 1799 | 130 | #define AUDIT_LAST_KERN_ANOM_MSG 1799 |
| 131 | #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ | 131 | #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ |
| 132 | #define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ | 132 | #define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ |
| 133 | #define AUDIT_ANOM_LINK 1702 /* Suspicious use of file links */ | ||
| 133 | #define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ | 134 | #define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ |
| 134 | #define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ | 135 | #define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ |
| 135 | #define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ | 136 | #define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ |
| @@ -687,6 +688,8 @@ extern void audit_log_d_path(struct audit_buffer *ab, | |||
| 687 | const struct path *path); | 688 | const struct path *path); |
| 688 | extern void audit_log_key(struct audit_buffer *ab, | 689 | extern void audit_log_key(struct audit_buffer *ab, |
| 689 | char *key); | 690 | char *key); |
| 691 | extern void audit_log_link_denied(const char *operation, | ||
| 692 | struct path *link); | ||
| 690 | extern void audit_log_lost(const char *message); | 693 | extern void audit_log_lost(const char *message); |
| 691 | #ifdef CONFIG_SECURITY | 694 | #ifdef CONFIG_SECURITY |
| 692 | extern void audit_log_secctx(struct audit_buffer *ab, u32 secid); | 695 | extern void audit_log_secctx(struct audit_buffer *ab, u32 secid); |
| @@ -716,6 +719,7 @@ extern int audit_enabled; | |||
| 716 | #define audit_log_untrustedstring(a,s) do { ; } while (0) | 719 | #define audit_log_untrustedstring(a,s) do { ; } while (0) |
| 717 | #define audit_log_d_path(b, p, d) do { ; } while (0) | 720 | #define audit_log_d_path(b, p, d) do { ; } while (0) |
| 718 | #define audit_log_key(b, k) do { ; } while (0) | 721 | #define audit_log_key(b, k) do { ; } while (0) |
| 722 | #define audit_log_link_denied(o, l) do { ; } while (0) | ||
| 719 | #define audit_log_secctx(b,s) do { ; } while (0) | 723 | #define audit_log_secctx(b,s) do { ; } while (0) |
| 720 | #define audit_enabled 0 | 724 | #define audit_enabled 0 |
| 721 | #endif | 725 | #endif |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 4ba5c8715523..38dba16c4176 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -414,6 +414,7 @@ struct inodes_stat_t { | |||
| 414 | #include <linux/shrinker.h> | 414 | #include <linux/shrinker.h> |
| 415 | #include <linux/migrate_mode.h> | 415 | #include <linux/migrate_mode.h> |
| 416 | #include <linux/uidgid.h> | 416 | #include <linux/uidgid.h> |
| 417 | #include <linux/lockdep.h> | ||
| 417 | 418 | ||
| 418 | #include <asm/byteorder.h> | 419 | #include <asm/byteorder.h> |
| 419 | 420 | ||
| @@ -440,6 +441,8 @@ extern unsigned long get_max_files(void); | |||
| 440 | extern int sysctl_nr_open; | 441 | extern int sysctl_nr_open; |
| 441 | extern struct inodes_stat_t inodes_stat; | 442 | extern struct inodes_stat_t inodes_stat; |
| 442 | extern int leases_enable, lease_break_time; | 443 | extern int leases_enable, lease_break_time; |
| 444 | extern int sysctl_protected_symlinks; | ||
| 445 | extern int sysctl_protected_hardlinks; | ||
| 443 | 446 | ||
| 444 | struct buffer_head; | 447 | struct buffer_head; |
| 445 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, | 448 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, |
| @@ -1445,6 +1448,8 @@ extern void f_delown(struct file *filp); | |||
| 1445 | extern pid_t f_getown(struct file *filp); | 1448 | extern pid_t f_getown(struct file *filp); |
| 1446 | extern int send_sigurg(struct fown_struct *fown); | 1449 | extern int send_sigurg(struct fown_struct *fown); |
| 1447 | 1450 | ||
| 1451 | struct mm_struct; | ||
| 1452 | |||
| 1448 | /* | 1453 | /* |
| 1449 | * Umount options | 1454 | * Umount options |
| 1450 | */ | 1455 | */ |
| @@ -1458,6 +1463,31 @@ extern int send_sigurg(struct fown_struct *fown); | |||
| 1458 | extern struct list_head super_blocks; | 1463 | extern struct list_head super_blocks; |
| 1459 | extern spinlock_t sb_lock; | 1464 | extern spinlock_t sb_lock; |
| 1460 | 1465 | ||
| 1466 | /* Possible states of 'frozen' field */ | ||
| 1467 | enum { | ||
| 1468 | SB_UNFROZEN = 0, /* FS is unfrozen */ | ||
| 1469 | SB_FREEZE_WRITE = 1, /* Writes, dir ops, ioctls frozen */ | ||
| 1470 | SB_FREEZE_PAGEFAULT = 2, /* Page faults stopped as well */ | ||
| 1471 | SB_FREEZE_FS = 3, /* For internal FS use (e.g. to stop | ||
| 1472 | * internal threads if needed) */ | ||
| 1473 | SB_FREEZE_COMPLETE = 4, /* ->freeze_fs finished successfully */ | ||
| 1474 | }; | ||
| 1475 | |||
| 1476 | #define SB_FREEZE_LEVELS (SB_FREEZE_COMPLETE - 1) | ||
| 1477 | |||
| 1478 | struct sb_writers { | ||
| 1479 | /* Counters for counting writers at each level */ | ||
| 1480 | struct percpu_counter counter[SB_FREEZE_LEVELS]; | ||
| 1481 | wait_queue_head_t wait; /* queue for waiting for | ||
| 1482 | writers / faults to finish */ | ||
| 1483 | int frozen; /* Is sb frozen? */ | ||
| 1484 | wait_queue_head_t wait_unfrozen; /* queue for waiting for | ||
| 1485 | sb to be thawed */ | ||
| 1486 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 1487 | struct lockdep_map lock_map[SB_FREEZE_LEVELS]; | ||
| 1488 | #endif | ||
| 1489 | }; | ||
| 1490 | |||
| 1461 | struct super_block { | 1491 | struct super_block { |
| 1462 | struct list_head s_list; /* Keep this first */ | 1492 | struct list_head s_list; /* Keep this first */ |
| 1463 | dev_t s_dev; /* search index; _not_ kdev_t */ | 1493 | dev_t s_dev; /* search index; _not_ kdev_t */ |
| @@ -1505,8 +1535,7 @@ struct super_block { | |||
| 1505 | struct hlist_node s_instances; | 1535 | struct hlist_node s_instances; |
| 1506 | struct quota_info s_dquot; /* Diskquota specific options */ | 1536 | struct quota_info s_dquot; /* Diskquota specific options */ |
| 1507 | 1537 | ||
| 1508 | int s_frozen; | 1538 | struct sb_writers s_writers; |
| 1509 | wait_queue_head_t s_wait_unfrozen; | ||
| 1510 | 1539 | ||
| 1511 | char s_id[32]; /* Informational name */ | 1540 | char s_id[32]; /* Informational name */ |
| 1512 | u8 s_uuid[16]; /* UUID */ | 1541 | u8 s_uuid[16]; /* UUID */ |
| @@ -1561,14 +1590,117 @@ extern struct timespec current_fs_time(struct super_block *sb); | |||
| 1561 | /* | 1590 | /* |
| 1562 | * Snapshotting support. | 1591 | * Snapshotting support. |
| 1563 | */ | 1592 | */ |
| 1564 | enum { | ||
| 1565 | SB_UNFROZEN = 0, | ||
| 1566 | SB_FREEZE_WRITE = 1, | ||
| 1567 | SB_FREEZE_TRANS = 2, | ||
| 1568 | }; | ||
| 1569 | 1593 | ||
| 1570 | #define vfs_check_frozen(sb, level) \ | 1594 | void __sb_end_write(struct super_block *sb, int level); |
| 1571 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) | 1595 | int __sb_start_write(struct super_block *sb, int level, bool wait); |
| 1596 | |||
| 1597 | /** | ||
| 1598 | * sb_end_write - drop write access to a superblock | ||
| 1599 | * @sb: the super we wrote to | ||
| 1600 | * | ||
| 1601 | * Decrement number of writers to the filesystem. Wake up possible waiters | ||
| 1602 | * wanting to freeze the filesystem. | ||
| 1603 | */ | ||
| 1604 | static inline void sb_end_write(struct super_block *sb) | ||
| 1605 | { | ||
| 1606 | __sb_end_write(sb, SB_FREEZE_WRITE); | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | /** | ||
| 1610 | * sb_end_pagefault - drop write access to a superblock from a page fault | ||
| 1611 | * @sb: the super we wrote to | ||
| 1612 | * | ||
| 1613 | * Decrement number of processes handling write page fault to the filesystem. | ||
| 1614 | * Wake up possible waiters wanting to freeze the filesystem. | ||
| 1615 | */ | ||
| 1616 | static inline void sb_end_pagefault(struct super_block *sb) | ||
| 1617 | { | ||
| 1618 | __sb_end_write(sb, SB_FREEZE_PAGEFAULT); | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | /** | ||
| 1622 | * sb_end_intwrite - drop write access to a superblock for internal fs purposes | ||
| 1623 | * @sb: the super we wrote to | ||
| 1624 | * | ||
| 1625 | * Decrement fs-internal number of writers to the filesystem. Wake up possible | ||
| 1626 | * waiters wanting to freeze the filesystem. | ||
| 1627 | */ | ||
| 1628 | static inline void sb_end_intwrite(struct super_block *sb) | ||
| 1629 | { | ||
| 1630 | __sb_end_write(sb, SB_FREEZE_FS); | ||
| 1631 | } | ||
| 1632 | |||
| 1633 | /** | ||
| 1634 | * sb_start_write - get write access to a superblock | ||
| 1635 | * @sb: the super we write to | ||
| 1636 | * | ||
| 1637 | * When a process wants to write data or metadata to a file system (i.e. dirty | ||
| 1638 | * a page or an inode), it should embed the operation in a sb_start_write() - | ||
| 1639 | * sb_end_write() pair to get exclusion against file system freezing. This | ||
| 1640 | * function increments number of writers preventing freezing. If the file | ||
| 1641 | * system is already frozen, the function waits until the file system is | ||
| 1642 | * thawed. | ||
| 1643 | * | ||
| 1644 | * Since freeze protection behaves as a lock, users have to preserve | ||
| 1645 | * ordering of freeze protection and other filesystem locks. Generally, | ||
| 1646 | * freeze protection should be the outermost lock. In particular, we have: | ||
| 1647 | * | ||
| 1648 | * sb_start_write | ||
| 1649 | * -> i_mutex (write path, truncate, directory ops, ...) | ||
| 1650 | * -> s_umount (freeze_super, thaw_super) | ||
| 1651 | */ | ||
| 1652 | static inline void sb_start_write(struct super_block *sb) | ||
| 1653 | { | ||
| 1654 | __sb_start_write(sb, SB_FREEZE_WRITE, true); | ||
| 1655 | } | ||
| 1656 | |||
| 1657 | static inline int sb_start_write_trylock(struct super_block *sb) | ||
| 1658 | { | ||
| 1659 | return __sb_start_write(sb, SB_FREEZE_WRITE, false); | ||
| 1660 | } | ||
| 1661 | |||
| 1662 | /** | ||
| 1663 | * sb_start_pagefault - get write access to a superblock from a page fault | ||
| 1664 | * @sb: the super we write to | ||
| 1665 | * | ||
| 1666 | * When a process starts handling write page fault, it should embed the | ||
| 1667 | * operation into sb_start_pagefault() - sb_end_pagefault() pair to get | ||
| 1668 | * exclusion against file system freezing. This is needed since the page fault | ||
| 1669 | * is going to dirty a page. This function increments number of running page | ||
| 1670 | * faults preventing freezing. If the file system is already frozen, the | ||
| 1671 | * function waits until the file system is thawed. | ||
| 1672 | * | ||
| 1673 | * Since page fault freeze protection behaves as a lock, users have to preserve | ||
| 1674 | * ordering of freeze protection and other filesystem locks. It is advised to | ||
| 1675 | * put sb_start_pagefault() close to mmap_sem in lock ordering. Page fault | ||
| 1676 | * handling code implies lock dependency: | ||
| 1677 | * | ||
| 1678 | * mmap_sem | ||
| 1679 | * -> sb_start_pagefault | ||
| 1680 | */ | ||
| 1681 | static inline void sb_start_pagefault(struct super_block *sb) | ||
| 1682 | { | ||
| 1683 | __sb_start_write(sb, SB_FREEZE_PAGEFAULT, true); | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | /* | ||
| 1687 | * sb_start_intwrite - get write access to a superblock for internal fs purposes | ||
| 1688 | * @sb: the super we write to | ||
| 1689 | * | ||
| 1690 | * This is the third level of protection against filesystem freezing. It is | ||
| 1691 | * free for use by a filesystem. The only requirement is that it must rank | ||
| 1692 | * below sb_start_pagefault. | ||
| 1693 | * | ||
| 1694 | * For example filesystem can call sb_start_intwrite() when starting a | ||
| 1695 | * transaction which somewhat eases handling of freezing for internal sources | ||
| 1696 | * of filesystem changes (internal fs threads, discarding preallocation on file | ||
| 1697 | * close, etc.). | ||
| 1698 | */ | ||
| 1699 | static inline void sb_start_intwrite(struct super_block *sb) | ||
| 1700 | { | ||
| 1701 | __sb_start_write(sb, SB_FREEZE_FS, true); | ||
| 1702 | } | ||
| 1703 | |||
| 1572 | 1704 | ||
| 1573 | extern bool inode_owner_or_capable(const struct inode *inode); | 1705 | extern bool inode_owner_or_capable(const struct inode *inode); |
| 1574 | 1706 | ||
| @@ -1892,6 +2024,7 @@ struct file_system_type { | |||
| 1892 | struct lock_class_key s_lock_key; | 2024 | struct lock_class_key s_lock_key; |
| 1893 | struct lock_class_key s_umount_key; | 2025 | struct lock_class_key s_umount_key; |
| 1894 | struct lock_class_key s_vfs_rename_key; | 2026 | struct lock_class_key s_vfs_rename_key; |
| 2027 | struct lock_class_key s_writers_key[SB_FREEZE_LEVELS]; | ||
| 1895 | 2028 | ||
| 1896 | struct lock_class_key i_lock_key; | 2029 | struct lock_class_key i_lock_key; |
| 1897 | struct lock_class_key i_mutex_key; | 2030 | struct lock_class_key i_mutex_key; |
| @@ -2334,9 +2467,6 @@ static inline void i_readcount_inc(struct inode *inode) | |||
| 2334 | } | 2467 | } |
| 2335 | #endif | 2468 | #endif |
| 2336 | extern int do_pipe_flags(int *, int); | 2469 | extern int do_pipe_flags(int *, int); |
| 2337 | extern struct file *create_read_pipe(struct file *f, int flags); | ||
| 2338 | extern struct file *create_write_pipe(int flags); | ||
| 2339 | extern void free_write_pipe(struct file *); | ||
| 2340 | 2470 | ||
| 2341 | extern int kernel_read(struct file *, loff_t, char *, unsigned long); | 2471 | extern int kernel_read(struct file *, loff_t, char *, unsigned long); |
| 2342 | extern struct file * open_exec(const char *); | 2472 | extern struct file * open_exec(const char *); |
diff --git a/include/linux/mm.h b/include/linux/mm.h index bd079a1b0fdc..311be906b57d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -1441,6 +1441,7 @@ extern void truncate_inode_pages_range(struct address_space *, | |||
| 1441 | 1441 | ||
| 1442 | /* generic vm_area_ops exported for stackable file systems */ | 1442 | /* generic vm_area_ops exported for stackable file systems */ |
| 1443 | extern int filemap_fault(struct vm_area_struct *, struct vm_fault *); | 1443 | extern int filemap_fault(struct vm_area_struct *, struct vm_fault *); |
| 1444 | extern int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); | ||
| 1444 | 1445 | ||
| 1445 | /* mm/page-writeback.c */ | 1446 | /* mm/page-writeback.c */ |
| 1446 | int write_one_page(struct page *page, int wait); | 1447 | int write_one_page(struct page *page, int wait); |
diff --git a/include/linux/namei.h b/include/linux/namei.h index d2ef8b34b967..4bf19d8174ed 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
| @@ -67,6 +67,7 @@ extern int kern_path(const char *, unsigned, struct path *); | |||
| 67 | 67 | ||
| 68 | extern struct dentry *kern_path_create(int, const char *, struct path *, int); | 68 | extern struct dentry *kern_path_create(int, const char *, struct path *, int); |
| 69 | extern struct dentry *user_path_create(int, const char __user *, struct path *, int); | 69 | extern struct dentry *user_path_create(int, const char __user *, struct path *, int); |
| 70 | extern void done_path_create(struct path *, struct dentry *); | ||
| 70 | extern struct dentry *kern_path_locked(const char *, struct path *); | 71 | extern struct dentry *kern_path_locked(const char *, struct path *); |
| 71 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, | 72 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, |
| 72 | const char *, unsigned int, struct path *); | 73 | const char *, unsigned int, struct path *); |
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index ce4743a26015..fa63048fecff 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h | |||
| @@ -143,6 +143,7 @@ typedef struct svc_fh { | |||
| 143 | int fh_maxsize; /* max size for fh_handle */ | 143 | int fh_maxsize; /* max size for fh_handle */ |
| 144 | 144 | ||
| 145 | unsigned char fh_locked; /* inode locked by us */ | 145 | unsigned char fh_locked; /* inode locked by us */ |
| 146 | unsigned char fh_want_write; /* remount protection taken */ | ||
| 146 | 147 | ||
| 147 | #ifdef CONFIG_NFSD_V3 | 148 | #ifdef CONFIG_NFSD_V3 |
| 148 | unsigned char fh_post_saved; /* post-op attrs saved */ | 149 | unsigned char fh_post_saved; /* post-op attrs saved */ |
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index e11d1c0fc60f..ad1a427b5267 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h | |||
| @@ -160,4 +160,6 @@ void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); | |||
| 160 | long pipe_fcntl(struct file *, unsigned int, unsigned long arg); | 160 | long pipe_fcntl(struct file *, unsigned int, unsigned long arg); |
| 161 | struct pipe_inode_info *get_pipe_info(struct file *file); | 161 | struct pipe_inode_info *get_pipe_info(struct file *file); |
| 162 | 162 | ||
| 163 | int create_pipe_files(struct file **, int); | ||
| 164 | |||
| 163 | #endif | 165 | #endif |
diff --git a/kernel/audit.c b/kernel/audit.c index 4a3f28d2ca65..ea3b7b6191c7 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -1456,6 +1456,27 @@ void audit_log_key(struct audit_buffer *ab, char *key) | |||
| 1456 | } | 1456 | } |
| 1457 | 1457 | ||
| 1458 | /** | 1458 | /** |
| 1459 | * audit_log_link_denied - report a link restriction denial | ||
| 1460 | * @operation: specific link opreation | ||
| 1461 | * @link: the path that triggered the restriction | ||
| 1462 | */ | ||
| 1463 | void audit_log_link_denied(const char *operation, struct path *link) | ||
| 1464 | { | ||
| 1465 | struct audit_buffer *ab; | ||
| 1466 | |||
| 1467 | ab = audit_log_start(current->audit_context, GFP_KERNEL, | ||
| 1468 | AUDIT_ANOM_LINK); | ||
| 1469 | audit_log_format(ab, "op=%s action=denied", operation); | ||
| 1470 | audit_log_format(ab, " pid=%d comm=", current->pid); | ||
| 1471 | audit_log_untrustedstring(ab, current->comm); | ||
| 1472 | audit_log_d_path(ab, " path=", link); | ||
| 1473 | audit_log_format(ab, " dev="); | ||
| 1474 | audit_log_untrustedstring(ab, link->dentry->d_inode->i_sb->s_id); | ||
| 1475 | audit_log_format(ab, " ino=%lu", link->dentry->d_inode->i_ino); | ||
| 1476 | audit_log_end(ab); | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | /** | ||
| 1459 | * audit_log_end - end one audit record | 1480 | * audit_log_end - end one audit record |
| 1460 | * @ab: the audit_buffer | 1481 | * @ab: the audit_buffer |
| 1461 | * | 1482 | * |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 6502d35a25ba..87174ef59161 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -1498,6 +1498,24 @@ static struct ctl_table fs_table[] = { | |||
| 1498 | #endif | 1498 | #endif |
| 1499 | #endif | 1499 | #endif |
| 1500 | { | 1500 | { |
| 1501 | .procname = "protected_symlinks", | ||
| 1502 | .data = &sysctl_protected_symlinks, | ||
| 1503 | .maxlen = sizeof(int), | ||
| 1504 | .mode = 0600, | ||
| 1505 | .proc_handler = proc_dointvec_minmax, | ||
| 1506 | .extra1 = &zero, | ||
| 1507 | .extra2 = &one, | ||
| 1508 | }, | ||
| 1509 | { | ||
| 1510 | .procname = "protected_hardlinks", | ||
| 1511 | .data = &sysctl_protected_hardlinks, | ||
| 1512 | .maxlen = sizeof(int), | ||
| 1513 | .mode = 0600, | ||
| 1514 | .proc_handler = proc_dointvec_minmax, | ||
| 1515 | .extra1 = &zero, | ||
| 1516 | .extra2 = &one, | ||
| 1517 | }, | ||
| 1518 | { | ||
| 1501 | .procname = "suid_dumpable", | 1519 | .procname = "suid_dumpable", |
| 1502 | .data = &suid_dumpable, | 1520 | .data = &suid_dumpable, |
| 1503 | .maxlen = sizeof(int), | 1521 | .maxlen = sizeof(int), |
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index f8a3f1a829b8..ba6085d9c741 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #ifdef CONFIG_HOTPLUG_CPU | 13 | #ifdef CONFIG_HOTPLUG_CPU |
| 14 | static LIST_HEAD(percpu_counters); | 14 | static LIST_HEAD(percpu_counters); |
| 15 | static DEFINE_MUTEX(percpu_counters_lock); | 15 | static DEFINE_SPINLOCK(percpu_counters_lock); |
| 16 | #endif | 16 | #endif |
| 17 | 17 | ||
| 18 | #ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER | 18 | #ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER |
| @@ -123,9 +123,9 @@ int __percpu_counter_init(struct percpu_counter *fbc, s64 amount, | |||
| 123 | 123 | ||
| 124 | #ifdef CONFIG_HOTPLUG_CPU | 124 | #ifdef CONFIG_HOTPLUG_CPU |
| 125 | INIT_LIST_HEAD(&fbc->list); | 125 | INIT_LIST_HEAD(&fbc->list); |
| 126 | mutex_lock(&percpu_counters_lock); | 126 | spin_lock(&percpu_counters_lock); |
| 127 | list_add(&fbc->list, &percpu_counters); | 127 | list_add(&fbc->list, &percpu_counters); |
| 128 | mutex_unlock(&percpu_counters_lock); | 128 | spin_unlock(&percpu_counters_lock); |
| 129 | #endif | 129 | #endif |
| 130 | return 0; | 130 | return 0; |
| 131 | } | 131 | } |
| @@ -139,9 +139,9 @@ void percpu_counter_destroy(struct percpu_counter *fbc) | |||
| 139 | debug_percpu_counter_deactivate(fbc); | 139 | debug_percpu_counter_deactivate(fbc); |
| 140 | 140 | ||
| 141 | #ifdef CONFIG_HOTPLUG_CPU | 141 | #ifdef CONFIG_HOTPLUG_CPU |
| 142 | mutex_lock(&percpu_counters_lock); | 142 | spin_lock(&percpu_counters_lock); |
| 143 | list_del(&fbc->list); | 143 | list_del(&fbc->list); |
| 144 | mutex_unlock(&percpu_counters_lock); | 144 | spin_unlock(&percpu_counters_lock); |
| 145 | #endif | 145 | #endif |
| 146 | free_percpu(fbc->counters); | 146 | free_percpu(fbc->counters); |
| 147 | fbc->counters = NULL; | 147 | fbc->counters = NULL; |
| @@ -170,7 +170,7 @@ static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb, | |||
| 170 | return NOTIFY_OK; | 170 | return NOTIFY_OK; |
| 171 | 171 | ||
| 172 | cpu = (unsigned long)hcpu; | 172 | cpu = (unsigned long)hcpu; |
| 173 | mutex_lock(&percpu_counters_lock); | 173 | spin_lock(&percpu_counters_lock); |
| 174 | list_for_each_entry(fbc, &percpu_counters, list) { | 174 | list_for_each_entry(fbc, &percpu_counters, list) { |
| 175 | s32 *pcount; | 175 | s32 *pcount; |
| 176 | unsigned long flags; | 176 | unsigned long flags; |
| @@ -181,7 +181,7 @@ static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb, | |||
| 181 | *pcount = 0; | 181 | *pcount = 0; |
| 182 | raw_spin_unlock_irqrestore(&fbc->lock, flags); | 182 | raw_spin_unlock_irqrestore(&fbc->lock, flags); |
| 183 | } | 183 | } |
| 184 | mutex_unlock(&percpu_counters_lock); | 184 | spin_unlock(&percpu_counters_lock); |
| 185 | #endif | 185 | #endif |
| 186 | return NOTIFY_OK; | 186 | return NOTIFY_OK; |
| 187 | } | 187 | } |
diff --git a/mm/filemap.c b/mm/filemap.c index a4a5260b0279..fa5ca304148e 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -1712,8 +1712,35 @@ page_not_uptodate: | |||
| 1712 | } | 1712 | } |
| 1713 | EXPORT_SYMBOL(filemap_fault); | 1713 | EXPORT_SYMBOL(filemap_fault); |
| 1714 | 1714 | ||
| 1715 | int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
| 1716 | { | ||
| 1717 | struct page *page = vmf->page; | ||
| 1718 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | ||
| 1719 | int ret = VM_FAULT_LOCKED; | ||
| 1720 | |||
| 1721 | sb_start_pagefault(inode->i_sb); | ||
| 1722 | file_update_time(vma->vm_file); | ||
| 1723 | lock_page(page); | ||
| 1724 | if (page->mapping != inode->i_mapping) { | ||
| 1725 | unlock_page(page); | ||
| 1726 | ret = VM_FAULT_NOPAGE; | ||
| 1727 | goto out; | ||
| 1728 | } | ||
| 1729 | /* | ||
| 1730 | * We mark the page dirty already here so that when freeze is in | ||
| 1731 | * progress, we are guaranteed that writeback during freezing will | ||
| 1732 | * see the dirty page and writeprotect it again. | ||
| 1733 | */ | ||
| 1734 | set_page_dirty(page); | ||
| 1735 | out: | ||
| 1736 | sb_end_pagefault(inode->i_sb); | ||
| 1737 | return ret; | ||
| 1738 | } | ||
| 1739 | EXPORT_SYMBOL(filemap_page_mkwrite); | ||
| 1740 | |||
| 1715 | const struct vm_operations_struct generic_file_vm_ops = { | 1741 | const struct vm_operations_struct generic_file_vm_ops = { |
| 1716 | .fault = filemap_fault, | 1742 | .fault = filemap_fault, |
| 1743 | .page_mkwrite = filemap_page_mkwrite, | ||
| 1717 | }; | 1744 | }; |
| 1718 | 1745 | ||
| 1719 | /* This is used for a general mmap of a disk file */ | 1746 | /* This is used for a general mmap of a disk file */ |
| @@ -2407,8 +2434,6 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 2407 | count = ocount; | 2434 | count = ocount; |
| 2408 | pos = *ppos; | 2435 | pos = *ppos; |
| 2409 | 2436 | ||
| 2410 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
| 2411 | |||
| 2412 | /* We can write back this queue in page reclaim */ | 2437 | /* We can write back this queue in page reclaim */ |
| 2413 | current->backing_dev_info = mapping->backing_dev_info; | 2438 | current->backing_dev_info = mapping->backing_dev_info; |
| 2414 | written = 0; | 2439 | written = 0; |
| @@ -2507,6 +2532,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 2507 | 2532 | ||
| 2508 | BUG_ON(iocb->ki_pos != pos); | 2533 | BUG_ON(iocb->ki_pos != pos); |
| 2509 | 2534 | ||
| 2535 | sb_start_write(inode->i_sb); | ||
| 2510 | mutex_lock(&inode->i_mutex); | 2536 | mutex_lock(&inode->i_mutex); |
| 2511 | blk_start_plug(&plug); | 2537 | blk_start_plug(&plug); |
| 2512 | ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); | 2538 | ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); |
| @@ -2520,6 +2546,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 2520 | ret = err; | 2546 | ret = err; |
| 2521 | } | 2547 | } |
| 2522 | blk_finish_plug(&plug); | 2548 | blk_finish_plug(&plug); |
| 2549 | sb_end_write(inode->i_sb); | ||
| 2523 | return ret; | 2550 | return ret; |
| 2524 | } | 2551 | } |
| 2525 | EXPORT_SYMBOL(generic_file_aio_write); | 2552 | EXPORT_SYMBOL(generic_file_aio_write); |
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index 213ca1f53409..13e013b1270c 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c | |||
| @@ -304,6 +304,7 @@ out: | |||
| 304 | 304 | ||
| 305 | static const struct vm_operations_struct xip_file_vm_ops = { | 305 | static const struct vm_operations_struct xip_file_vm_ops = { |
| 306 | .fault = xip_file_fault, | 306 | .fault = xip_file_fault, |
| 307 | .page_mkwrite = filemap_page_mkwrite, | ||
| 307 | }; | 308 | }; |
| 308 | 309 | ||
| 309 | int xip_file_mmap(struct file * file, struct vm_area_struct * vma) | 310 | int xip_file_mmap(struct file * file, struct vm_area_struct * vma) |
| @@ -401,6 +402,8 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, | |||
| 401 | loff_t pos; | 402 | loff_t pos; |
| 402 | ssize_t ret; | 403 | ssize_t ret; |
| 403 | 404 | ||
| 405 | sb_start_write(inode->i_sb); | ||
| 406 | |||
| 404 | mutex_lock(&inode->i_mutex); | 407 | mutex_lock(&inode->i_mutex); |
| 405 | 408 | ||
| 406 | if (!access_ok(VERIFY_READ, buf, len)) { | 409 | if (!access_ok(VERIFY_READ, buf, len)) { |
| @@ -411,8 +414,6 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, | |||
| 411 | pos = *ppos; | 414 | pos = *ppos; |
| 412 | count = len; | 415 | count = len; |
| 413 | 416 | ||
| 414 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
| 415 | |||
| 416 | /* We can write back this queue in page reclaim */ | 417 | /* We can write back this queue in page reclaim */ |
| 417 | current->backing_dev_info = mapping->backing_dev_info; | 418 | current->backing_dev_info = mapping->backing_dev_info; |
| 418 | 419 | ||
| @@ -436,6 +437,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, | |||
| 436 | current->backing_dev_info = NULL; | 437 | current->backing_dev_info = NULL; |
| 437 | out_up: | 438 | out_up: |
| 438 | mutex_unlock(&inode->i_mutex); | 439 | mutex_unlock(&inode->i_mutex); |
| 440 | sb_end_write(inode->i_sb); | ||
| 439 | return ret; | 441 | return ret; |
| 440 | } | 442 | } |
| 441 | EXPORT_SYMBOL_GPL(xip_file_write); | 443 | EXPORT_SYMBOL_GPL(xip_file_write); |
diff --git a/mm/memory.c b/mm/memory.c index 482f089765ff..57361708d1a5 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -2650,6 +2650,9 @@ reuse: | |||
| 2650 | if (!page_mkwrite) { | 2650 | if (!page_mkwrite) { |
| 2651 | wait_on_page_locked(dirty_page); | 2651 | wait_on_page_locked(dirty_page); |
| 2652 | set_page_dirty_balance(dirty_page, page_mkwrite); | 2652 | set_page_dirty_balance(dirty_page, page_mkwrite); |
| 2653 | /* file_update_time outside page_lock */ | ||
| 2654 | if (vma->vm_file) | ||
| 2655 | file_update_time(vma->vm_file); | ||
| 2653 | } | 2656 | } |
| 2654 | put_page(dirty_page); | 2657 | put_page(dirty_page); |
| 2655 | if (page_mkwrite) { | 2658 | if (page_mkwrite) { |
| @@ -2667,10 +2670,6 @@ reuse: | |||
| 2667 | } | 2670 | } |
| 2668 | } | 2671 | } |
| 2669 | 2672 | ||
| 2670 | /* file_update_time outside page_lock */ | ||
| 2671 | if (vma->vm_file) | ||
| 2672 | file_update_time(vma->vm_file); | ||
| 2673 | |||
| 2674 | return ret; | 2673 | return ret; |
| 2675 | } | 2674 | } |
| 2676 | 2675 | ||
| @@ -3339,12 +3338,13 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 3339 | 3338 | ||
| 3340 | if (dirty_page) { | 3339 | if (dirty_page) { |
| 3341 | struct address_space *mapping = page->mapping; | 3340 | struct address_space *mapping = page->mapping; |
| 3341 | int dirtied = 0; | ||
| 3342 | 3342 | ||
| 3343 | if (set_page_dirty(dirty_page)) | 3343 | if (set_page_dirty(dirty_page)) |
| 3344 | page_mkwrite = 1; | 3344 | dirtied = 1; |
| 3345 | unlock_page(dirty_page); | 3345 | unlock_page(dirty_page); |
| 3346 | put_page(dirty_page); | 3346 | put_page(dirty_page); |
| 3347 | if (page_mkwrite && mapping) { | 3347 | if ((dirtied || page_mkwrite) && mapping) { |
| 3348 | /* | 3348 | /* |
| 3349 | * Some device drivers do not set page.mapping but still | 3349 | * Some device drivers do not set page.mapping but still |
| 3350 | * dirty their pages | 3350 | * dirty their pages |
| @@ -3353,7 +3353,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 3353 | } | 3353 | } |
| 3354 | 3354 | ||
| 3355 | /* file_update_time outside page_lock */ | 3355 | /* file_update_time outside page_lock */ |
| 3356 | if (vma->vm_file) | 3356 | if (vma->vm_file && !page_mkwrite) |
| 3357 | file_update_time(vma->vm_file); | 3357 | file_update_time(vma->vm_file); |
| 3358 | } else { | 3358 | } else { |
| 3359 | unlock_page(vmf.page); | 3359 | unlock_page(vmf.page); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 79981d97bc9c..e4768c180da2 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -823,6 +823,34 @@ fail: | |||
| 823 | return NULL; | 823 | return NULL; |
| 824 | } | 824 | } |
| 825 | 825 | ||
| 826 | static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) | ||
| 827 | { | ||
| 828 | struct dentry *dentry; | ||
| 829 | struct path path; | ||
| 830 | int err = 0; | ||
| 831 | /* | ||
| 832 | * Get the parent directory, calculate the hash for last | ||
| 833 | * component. | ||
| 834 | */ | ||
| 835 | dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | ||
| 836 | err = PTR_ERR(dentry); | ||
| 837 | if (IS_ERR(dentry)) | ||
| 838 | return err; | ||
| 839 | |||
| 840 | /* | ||
| 841 | * All right, let's create it. | ||
| 842 | */ | ||
| 843 | err = security_path_mknod(&path, dentry, mode, 0); | ||
| 844 | if (!err) { | ||
| 845 | err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0); | ||
| 846 | if (!err) { | ||
| 847 | res->mnt = mntget(path.mnt); | ||
| 848 | res->dentry = dget(dentry); | ||
| 849 | } | ||
| 850 | } | ||
| 851 | done_path_create(&path, dentry); | ||
| 852 | return err; | ||
| 853 | } | ||
| 826 | 854 | ||
| 827 | static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | 855 | static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
| 828 | { | 856 | { |
| @@ -831,8 +859,6 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 831 | struct unix_sock *u = unix_sk(sk); | 859 | struct unix_sock *u = unix_sk(sk); |
| 832 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; | 860 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
| 833 | char *sun_path = sunaddr->sun_path; | 861 | char *sun_path = sunaddr->sun_path; |
| 834 | struct dentry *dentry = NULL; | ||
| 835 | struct path path; | ||
| 836 | int err; | 862 | int err; |
| 837 | unsigned int hash; | 863 | unsigned int hash; |
| 838 | struct unix_address *addr; | 864 | struct unix_address *addr; |
| @@ -869,43 +895,23 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 869 | atomic_set(&addr->refcnt, 1); | 895 | atomic_set(&addr->refcnt, 1); |
| 870 | 896 | ||
| 871 | if (sun_path[0]) { | 897 | if (sun_path[0]) { |
| 872 | umode_t mode; | 898 | struct path path; |
| 873 | err = 0; | 899 | umode_t mode = S_IFSOCK | |
| 874 | /* | ||
| 875 | * Get the parent directory, calculate the hash for last | ||
| 876 | * component. | ||
| 877 | */ | ||
| 878 | dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | ||
| 879 | err = PTR_ERR(dentry); | ||
| 880 | if (IS_ERR(dentry)) | ||
| 881 | goto out_mknod_parent; | ||
| 882 | |||
| 883 | /* | ||
| 884 | * All right, let's create it. | ||
| 885 | */ | ||
| 886 | mode = S_IFSOCK | | ||
| 887 | (SOCK_INODE(sock)->i_mode & ~current_umask()); | 900 | (SOCK_INODE(sock)->i_mode & ~current_umask()); |
| 888 | err = mnt_want_write(path.mnt); | 901 | err = unix_mknod(sun_path, mode, &path); |
| 889 | if (err) | 902 | if (err) { |
| 890 | goto out_mknod_dput; | 903 | if (err == -EEXIST) |
| 891 | err = security_path_mknod(&path, dentry, mode, 0); | 904 | err = -EADDRINUSE; |
| 892 | if (err) | 905 | unix_release_addr(addr); |
| 893 | goto out_mknod_drop_write; | 906 | goto out_up; |
| 894 | err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0); | 907 | } |
| 895 | out_mknod_drop_write: | ||
| 896 | mnt_drop_write(path.mnt); | ||
| 897 | if (err) | ||
| 898 | goto out_mknod_dput; | ||
| 899 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
| 900 | dput(path.dentry); | ||
| 901 | path.dentry = dentry; | ||
| 902 | |||
| 903 | addr->hash = UNIX_HASH_SIZE; | 908 | addr->hash = UNIX_HASH_SIZE; |
| 904 | } | 909 | hash = path.dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1); |
| 905 | 910 | spin_lock(&unix_table_lock); | |
| 906 | spin_lock(&unix_table_lock); | 911 | u->path = path; |
| 907 | 912 | list = &unix_socket_table[hash]; | |
| 908 | if (!sun_path[0]) { | 913 | } else { |
| 914 | spin_lock(&unix_table_lock); | ||
| 909 | err = -EADDRINUSE; | 915 | err = -EADDRINUSE; |
| 910 | if (__unix_find_socket_byname(net, sunaddr, addr_len, | 916 | if (__unix_find_socket_byname(net, sunaddr, addr_len, |
| 911 | sk->sk_type, hash)) { | 917 | sk->sk_type, hash)) { |
| @@ -914,9 +920,6 @@ out_mknod_drop_write: | |||
| 914 | } | 920 | } |
| 915 | 921 | ||
| 916 | list = &unix_socket_table[addr->hash]; | 922 | list = &unix_socket_table[addr->hash]; |
| 917 | } else { | ||
| 918 | list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; | ||
| 919 | u->path = path; | ||
| 920 | } | 923 | } |
| 921 | 924 | ||
| 922 | err = 0; | 925 | err = 0; |
| @@ -930,16 +933,6 @@ out_up: | |||
| 930 | mutex_unlock(&u->readlock); | 933 | mutex_unlock(&u->readlock); |
| 931 | out: | 934 | out: |
| 932 | return err; | 935 | return err; |
| 933 | |||
| 934 | out_mknod_dput: | ||
| 935 | dput(dentry); | ||
| 936 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
| 937 | path_put(&path); | ||
| 938 | out_mknod_parent: | ||
| 939 | if (err == -EEXIST) | ||
| 940 | err = -EADDRINUSE; | ||
| 941 | unix_release_addr(addr); | ||
| 942 | goto out_up; | ||
| 943 | } | 936 | } |
| 944 | 937 | ||
| 945 | static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) | 938 | static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) |
diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c index 7e96249536b4..37711a5d0d6b 100644 --- a/sound/sound_firmware.c +++ b/sound/sound_firmware.c | |||
| @@ -23,14 +23,14 @@ static int do_mod_firmware_load(const char *fn, char **fp) | |||
| 23 | if (l <= 0 || l > 131072) | 23 | if (l <= 0 || l > 131072) |
| 24 | { | 24 | { |
| 25 | printk(KERN_INFO "Invalid firmware '%s'\n", fn); | 25 | printk(KERN_INFO "Invalid firmware '%s'\n", fn); |
| 26 | filp_close(filp, current->files); | 26 | filp_close(filp, NULL); |
| 27 | return 0; | 27 | return 0; |
| 28 | } | 28 | } |
| 29 | dp = vmalloc(l); | 29 | dp = vmalloc(l); |
| 30 | if (dp == NULL) | 30 | if (dp == NULL) |
| 31 | { | 31 | { |
| 32 | printk(KERN_INFO "Out of memory loading '%s'.\n", fn); | 32 | printk(KERN_INFO "Out of memory loading '%s'.\n", fn); |
| 33 | filp_close(filp, current->files); | 33 | filp_close(filp, NULL); |
| 34 | return 0; | 34 | return 0; |
| 35 | } | 35 | } |
| 36 | pos = 0; | 36 | pos = 0; |
| @@ -38,10 +38,10 @@ static int do_mod_firmware_load(const char *fn, char **fp) | |||
| 38 | { | 38 | { |
| 39 | printk(KERN_INFO "Failed to read '%s'.\n", fn); | 39 | printk(KERN_INFO "Failed to read '%s'.\n", fn); |
| 40 | vfree(dp); | 40 | vfree(dp); |
| 41 | filp_close(filp, current->files); | 41 | filp_close(filp, NULL); |
| 42 | return 0; | 42 | return 0; |
| 43 | } | 43 | } |
| 44 | filp_close(filp, current->files); | 44 | filp_close(filp, NULL); |
| 45 | *fp = dp; | 45 | *fp = dp; |
| 46 | return (int) l; | 46 | return (int) l; |
| 47 | } | 47 | } |
