[PATCH] Fix error handling with put_compat_statfs()

In fs/compat.c, whenever put_compat_statfs() returns an error, the
containing syscall returns -EFAULT. This is presumably by analogy with the
non-compat case, where any non-zero code from copy_to_user() should be
translated into an EFAULT. However, put_compat_statfs() is also return
-EOVERFLOW. The same applies for put_compat_statfs64().

This bug can be observed with a statfs() on a hugetlbfs directory.
hugetlbfs, when mounted without limits reports available, free and total
blocks as -1 (itself a bug, another patch coming). statfs() will
mysteriously return EFAULT although it's parameters are perfectly valid
addresses.

This patch causes the compat versions of statfs() and statfs64() to
correctly propogate the return values from put_compat_statfs() and
put_compat_statfs64().

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by David Gibson and committed by Linus Torvalds 86e07ce7 f3d48f03

+8 -8
+8 -8
fs/compat.c
··· 168 if (!error) { 169 struct kstatfs tmp; 170 error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); 171 - if (!error && put_compat_statfs(buf, &tmp)) 172 - error = -EFAULT; 173 path_release(&nd); 174 } 175 return error; ··· 186 if (!file) 187 goto out; 188 error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); 189 - if (!error && put_compat_statfs(buf, &tmp)) 190 - error = -EFAULT; 191 fput(file); 192 out: 193 return error; ··· 236 if (!error) { 237 struct kstatfs tmp; 238 error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); 239 - if (!error && put_compat_statfs64(buf, &tmp)) 240 - error = -EFAULT; 241 path_release(&nd); 242 } 243 return error; ··· 257 if (!file) 258 goto out; 259 error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); 260 - if (!error && put_compat_statfs64(buf, &tmp)) 261 - error = -EFAULT; 262 fput(file); 263 out: 264 return error;
··· 168 if (!error) { 169 struct kstatfs tmp; 170 error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); 171 + if (!error) 172 + error = put_compat_statfs(buf, &tmp); 173 path_release(&nd); 174 } 175 return error; ··· 186 if (!file) 187 goto out; 188 error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); 189 + if (!error) 190 + error = put_compat_statfs(buf, &tmp); 191 fput(file); 192 out: 193 return error; ··· 236 if (!error) { 237 struct kstatfs tmp; 238 error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); 239 + if (!error) 240 + error = put_compat_statfs64(buf, &tmp); 241 path_release(&nd); 242 } 243 return error; ··· 257 if (!file) 258 goto out; 259 error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); 260 + if (!error) 261 + error = put_compat_statfs64(buf, &tmp); 262 fput(file); 263 out: 264 return error;