diff options
author | Konstantin Khlebnikov <koct9i@gmail.com> | 2014-08-06 19:06:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 21:01:18 -0400 |
commit | 66ee4b8887ec5ce04bae3e840d206db7b7ad34d1 (patch) | |
tree | ca202430d326aaca6ad5f11e7296ccf1956aa961 /mm | |
parent | ef6b571fb8920d5006349a6e29ac47c4817e9691 (diff) |
shmem: fix double uncharge in __shmem_file_setup()
If __shmem_file_setup() fails on struct file allocation it uncharges
memory commitment twice: first by shmem_unacct_size() and second time
implicitly in shmem_evict_inode() when it kills the newly created inode.
This patch removes shmem_unacct_size() from error path if the inode was
already there.
Signed-off-by: Konstantin Khlebnikov <koct9i@gmail.com>
Acked-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/shmem.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index af68b15a8fc1..3609d31ad0dd 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -2932,16 +2932,16 @@ static struct file *__shmem_file_setup(const char *name, loff_t size, | |||
2932 | this.len = strlen(name); | 2932 | this.len = strlen(name); |
2933 | this.hash = 0; /* will go */ | 2933 | this.hash = 0; /* will go */ |
2934 | sb = shm_mnt->mnt_sb; | 2934 | sb = shm_mnt->mnt_sb; |
2935 | path.mnt = mntget(shm_mnt); | ||
2935 | path.dentry = d_alloc_pseudo(sb, &this); | 2936 | path.dentry = d_alloc_pseudo(sb, &this); |
2936 | if (!path.dentry) | 2937 | if (!path.dentry) |
2937 | goto put_memory; | 2938 | goto put_memory; |
2938 | d_set_d_op(path.dentry, &anon_ops); | 2939 | d_set_d_op(path.dentry, &anon_ops); |
2939 | path.mnt = mntget(shm_mnt); | ||
2940 | 2940 | ||
2941 | res = ERR_PTR(-ENOSPC); | 2941 | res = ERR_PTR(-ENOSPC); |
2942 | inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags); | 2942 | inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags); |
2943 | if (!inode) | 2943 | if (!inode) |
2944 | goto put_dentry; | 2944 | goto put_memory; |
2945 | 2945 | ||
2946 | inode->i_flags |= i_flags; | 2946 | inode->i_flags |= i_flags; |
2947 | d_instantiate(path.dentry, inode); | 2947 | d_instantiate(path.dentry, inode); |
@@ -2949,19 +2949,19 @@ static struct file *__shmem_file_setup(const char *name, loff_t size, | |||
2949 | clear_nlink(inode); /* It is unlinked */ | 2949 | clear_nlink(inode); /* It is unlinked */ |
2950 | res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size)); | 2950 | res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size)); |
2951 | if (IS_ERR(res)) | 2951 | if (IS_ERR(res)) |
2952 | goto put_dentry; | 2952 | goto put_path; |
2953 | 2953 | ||
2954 | res = alloc_file(&path, FMODE_WRITE | FMODE_READ, | 2954 | res = alloc_file(&path, FMODE_WRITE | FMODE_READ, |
2955 | &shmem_file_operations); | 2955 | &shmem_file_operations); |
2956 | if (IS_ERR(res)) | 2956 | if (IS_ERR(res)) |
2957 | goto put_dentry; | 2957 | goto put_path; |
2958 | 2958 | ||
2959 | return res; | 2959 | return res; |
2960 | 2960 | ||
2961 | put_dentry: | ||
2962 | path_put(&path); | ||
2963 | put_memory: | 2961 | put_memory: |
2964 | shmem_unacct_size(flags, size); | 2962 | shmem_unacct_size(flags, size); |
2963 | put_path: | ||
2964 | path_put(&path); | ||
2965 | return res; | 2965 | return res; |
2966 | } | 2966 | } |
2967 | 2967 | ||