Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clean statfs-like syscalls up

New helpers: user_statfs() and fd_statfs(), taking userland pathname and
descriptor resp. and filling struct kstatfs. Syscalls of statfs family
(native, compat and foreign - osf and hpux on alpha and parisc resp.)
switched to those. Removes some boilerplate code, simplifies cleanup
on errors...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro c8b91acc 73d049a4

+133 -214
+8 -28
arch/alpha/kernel/osf_sys.c
··· 230 230 return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0; 231 231 } 232 232 233 - static int 234 - do_osf_statfs(struct path *path, struct osf_statfs __user *buffer, 235 - unsigned long bufsiz) 233 + SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname, 234 + struct osf_statfs __user *, buffer, unsigned long, bufsiz) 236 235 { 237 236 struct kstatfs linux_stat; 238 - int error = vfs_statfs(path, &linux_stat); 237 + int error = user_statfs(pathname, &linux_stat); 239 238 if (!error) 240 239 error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); 241 240 return error; 242 241 } 243 242 244 - SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname, 245 - struct osf_statfs __user *, buffer, unsigned long, bufsiz) 246 - { 247 - struct path path; 248 - int retval; 249 - 250 - retval = user_path(pathname, &path); 251 - if (!retval) { 252 - retval = do_osf_statfs(&path, buffer, bufsiz); 253 - path_put(&path); 254 - } 255 - return retval; 256 - } 257 - 258 243 SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd, 259 244 struct osf_statfs __user *, buffer, unsigned long, bufsiz) 260 245 { 261 - struct file *file; 262 - int retval; 263 - 264 - retval = -EBADF; 265 - file = fget(fd); 266 - if (file) { 267 - retval = do_osf_statfs(&file->f_path, buffer, bufsiz); 268 - fput(file); 269 - } 270 - return retval; 246 + struct kstatfs linux_stat; 247 + int error = fd_statfs(fd, &linux_stat); 248 + if (!error) 249 + error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); 250 + return error; 271 251 } 272 252 273 253 /*
+22 -43
arch/parisc/hpux/sys_hpux.c
··· 185 185 int16_t f_pad; 186 186 }; 187 187 188 - static int do_statfs_hpux(struct path *path, struct hpux_statfs *buf) 188 + static int do_statfs_hpux(struct kstatfs *st, struct hpux_statfs __user *p) 189 189 { 190 - struct kstatfs st; 191 - int retval; 192 - 193 - retval = vfs_statfs(path, &st); 194 - if (retval) 195 - return retval; 196 - 197 - memset(buf, 0, sizeof(*buf)); 198 - buf->f_type = st.f_type; 199 - buf->f_bsize = st.f_bsize; 200 - buf->f_blocks = st.f_blocks; 201 - buf->f_bfree = st.f_bfree; 202 - buf->f_bavail = st.f_bavail; 203 - buf->f_files = st.f_files; 204 - buf->f_ffree = st.f_ffree; 205 - buf->f_fsid[0] = st.f_fsid.val[0]; 206 - buf->f_fsid[1] = st.f_fsid.val[1]; 207 - 190 + struct hpux_statfs buf; 191 + memset(&buf, 0, sizeof(buf)); 192 + buf.f_type = st->f_type; 193 + buf.f_bsize = st->f_bsize; 194 + buf.f_blocks = st->f_blocks; 195 + buf.f_bfree = st->f_bfree; 196 + buf.f_bavail = st->f_bavail; 197 + buf.f_files = st->f_files; 198 + buf.f_ffree = st->f_ffree; 199 + buf.f_fsid[0] = st->f_fsid.val[0]; 200 + buf.f_fsid[1] = st->f_fsid.val[1]; 201 + if (copy_to_user(p, &buf, sizeof(buf))) 202 + return -EFAULT; 208 203 return 0; 209 204 } 210 205 ··· 207 212 asmlinkage long hpux_statfs(const char __user *pathname, 208 213 struct hpux_statfs __user *buf) 209 214 { 210 - struct path path; 211 - int error; 212 - 213 - error = user_path(pathname, &path); 214 - if (!error) { 215 - struct hpux_statfs tmp; 216 - error = do_statfs_hpux(&path, &tmp); 217 - if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 218 - error = -EFAULT; 219 - path_put(&path); 220 - } 215 + struct kstatfs st; 216 + int error = user_statfs(pathname, &st); 217 + if (!error) 218 + error = do_statfs_hpux(&st, buf); 221 219 return error; 222 220 } 223 221 224 222 asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf) 225 223 { 226 - struct file *file; 227 - struct hpux_statfs tmp; 228 - int error; 229 - 230 - error = -EBADF; 231 - file = fget(fd); 232 - if (!file) 233 - goto out; 234 - error = do_statfs_hpux(&file->f_path, &tmp); 235 - if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 236 - error = -EFAULT; 237 - fput(file); 238 - out: 224 + struct kstatfs st; 225 + int error = fd_statfs(fd, &st); 226 + if (!error) 227 + error = do_statfs_hpux(&st, buf); 239 228 return error; 240 229 } 241 230
+20 -48
fs/compat.c
··· 262 262 */ 263 263 asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf) 264 264 { 265 - struct path path; 266 - int error; 267 - 268 - error = user_path(pathname, &path); 269 - if (!error) { 270 - struct kstatfs tmp; 271 - error = vfs_statfs(&path, &tmp); 272 - if (!error) 273 - error = put_compat_statfs(buf, &tmp); 274 - path_put(&path); 275 - } 265 + struct kstatfs tmp; 266 + int error = user_statfs(pathname, &tmp); 267 + if (!error) 268 + error = put_compat_statfs(buf, &tmp); 276 269 return error; 277 270 } 278 271 279 272 asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf) 280 273 { 281 - struct file * file; 282 274 struct kstatfs tmp; 283 - int error; 284 - 285 - error = -EBADF; 286 - file = fget(fd); 287 - if (!file) 288 - goto out; 289 - error = vfs_statfs(&file->f_path, &tmp); 275 + int error = fd_statfs(fd, &tmp); 290 276 if (!error) 291 277 error = put_compat_statfs(buf, &tmp); 292 - fput(file); 293 - out: 294 278 return error; 295 279 } 296 280 ··· 313 329 314 330 asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf) 315 331 { 316 - struct path path; 317 - int error; 318 - 319 - if (sz != sizeof(*buf)) 320 - return -EINVAL; 321 - 322 - error = user_path(pathname, &path); 323 - if (!error) { 324 - struct kstatfs tmp; 325 - error = vfs_statfs(&path, &tmp); 326 - if (!error) 327 - error = put_compat_statfs64(buf, &tmp); 328 - path_put(&path); 329 - } 330 - return error; 331 - } 332 - 333 - asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf) 334 - { 335 - struct file * file; 336 332 struct kstatfs tmp; 337 333 int error; 338 334 339 335 if (sz != sizeof(*buf)) 340 336 return -EINVAL; 341 337 342 - error = -EBADF; 343 - file = fget(fd); 344 - if (!file) 345 - goto out; 346 - error = vfs_statfs(&file->f_path, &tmp); 338 + error = user_statfs(pathname, &tmp); 347 339 if (!error) 348 340 error = put_compat_statfs64(buf, &tmp); 349 - fput(file); 350 - out: 341 + return error; 342 + } 343 + 344 + asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf) 345 + { 346 + struct kstatfs tmp; 347 + int error; 348 + 349 + if (sz != sizeof(*buf)) 350 + return -EINVAL; 351 + 352 + error = fd_statfs(fd, &tmp); 353 + if (!error) 354 + error = put_compat_statfs64(buf, &tmp); 351 355 return error; 352 356 } 353 357
+81 -95
fs/statfs.c
··· 73 73 } 74 74 EXPORT_SYMBOL(vfs_statfs); 75 75 76 - static int do_statfs_native(struct path *path, struct statfs *buf) 76 + int user_statfs(const char __user *pathname, struct kstatfs *st) 77 77 { 78 - struct kstatfs st; 79 - int retval; 78 + struct path path; 79 + int error = user_path(pathname, &path); 80 + if (!error) { 81 + error = vfs_statfs(&path, st); 82 + path_put(&path); 83 + } 84 + return error; 85 + } 80 86 81 - retval = vfs_statfs(path, &st); 82 - if (retval) 83 - return retval; 87 + int fd_statfs(int fd, struct kstatfs *st) 88 + { 89 + struct file *file = fget(fd); 90 + int error = -EBADF; 91 + if (file) { 92 + error = vfs_statfs(&file->f_path, st); 93 + fput(file); 94 + } 95 + return error; 96 + } 84 97 85 - if (sizeof(*buf) == sizeof(st)) 86 - memcpy(buf, &st, sizeof(st)); 98 + static int do_statfs_native(struct kstatfs *st, struct statfs __user *p) 99 + { 100 + struct statfs buf; 101 + 102 + if (sizeof(buf) == sizeof(*st)) 103 + memcpy(&buf, st, sizeof(*st)); 87 104 else { 88 - if (sizeof buf->f_blocks == 4) { 89 - if ((st.f_blocks | st.f_bfree | st.f_bavail | 90 - st.f_bsize | st.f_frsize) & 105 + if (sizeof buf.f_blocks == 4) { 106 + if ((st->f_blocks | st->f_bfree | st->f_bavail | 107 + st->f_bsize | st->f_frsize) & 91 108 0xffffffff00000000ULL) 92 109 return -EOVERFLOW; 93 110 /* 94 111 * f_files and f_ffree may be -1; it's okay to stuff 95 112 * that into 32 bits 96 113 */ 97 - if (st.f_files != -1 && 98 - (st.f_files & 0xffffffff00000000ULL)) 114 + if (st->f_files != -1 && 115 + (st->f_files & 0xffffffff00000000ULL)) 99 116 return -EOVERFLOW; 100 - if (st.f_ffree != -1 && 101 - (st.f_ffree & 0xffffffff00000000ULL)) 117 + if (st->f_ffree != -1 && 118 + (st->f_ffree & 0xffffffff00000000ULL)) 102 119 return -EOVERFLOW; 103 120 } 104 121 105 - buf->f_type = st.f_type; 106 - buf->f_bsize = st.f_bsize; 107 - buf->f_blocks = st.f_blocks; 108 - buf->f_bfree = st.f_bfree; 109 - buf->f_bavail = st.f_bavail; 110 - buf->f_files = st.f_files; 111 - buf->f_ffree = st.f_ffree; 112 - buf->f_fsid = st.f_fsid; 113 - buf->f_namelen = st.f_namelen; 114 - buf->f_frsize = st.f_frsize; 115 - buf->f_flags = st.f_flags; 116 - memset(buf->f_spare, 0, sizeof(buf->f_spare)); 122 + buf.f_type = st->f_type; 123 + buf.f_bsize = st->f_bsize; 124 + buf.f_blocks = st->f_blocks; 125 + buf.f_bfree = st->f_bfree; 126 + buf.f_bavail = st->f_bavail; 127 + buf.f_files = st->f_files; 128 + buf.f_ffree = st->f_ffree; 129 + buf.f_fsid = st->f_fsid; 130 + buf.f_namelen = st->f_namelen; 131 + buf.f_frsize = st->f_frsize; 132 + buf.f_flags = st->f_flags; 133 + memset(buf.f_spare, 0, sizeof(buf.f_spare)); 117 134 } 135 + if (copy_to_user(p, &buf, sizeof(buf))) 136 + return -EFAULT; 118 137 return 0; 119 138 } 120 139 121 - static int do_statfs64(struct path *path, struct statfs64 *buf) 140 + static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p) 122 141 { 123 - struct kstatfs st; 124 - int retval; 125 - 126 - retval = vfs_statfs(path, &st); 127 - if (retval) 128 - return retval; 129 - 130 - if (sizeof(*buf) == sizeof(st)) 131 - memcpy(buf, &st, sizeof(st)); 142 + struct statfs64 buf; 143 + if (sizeof(buf) == sizeof(*st)) 144 + memcpy(&buf, st, sizeof(*st)); 132 145 else { 133 - buf->f_type = st.f_type; 134 - buf->f_bsize = st.f_bsize; 135 - buf->f_blocks = st.f_blocks; 136 - buf->f_bfree = st.f_bfree; 137 - buf->f_bavail = st.f_bavail; 138 - buf->f_files = st.f_files; 139 - buf->f_ffree = st.f_ffree; 140 - buf->f_fsid = st.f_fsid; 141 - buf->f_namelen = st.f_namelen; 142 - buf->f_frsize = st.f_frsize; 143 - buf->f_flags = st.f_flags; 144 - memset(buf->f_spare, 0, sizeof(buf->f_spare)); 146 + buf.f_type = st->f_type; 147 + buf.f_bsize = st->f_bsize; 148 + buf.f_blocks = st->f_blocks; 149 + buf.f_bfree = st->f_bfree; 150 + buf.f_bavail = st->f_bavail; 151 + buf.f_files = st->f_files; 152 + buf.f_ffree = st->f_ffree; 153 + buf.f_fsid = st->f_fsid; 154 + buf.f_namelen = st->f_namelen; 155 + buf.f_frsize = st->f_frsize; 156 + buf.f_flags = st->f_flags; 157 + memset(buf.f_spare, 0, sizeof(buf.f_spare)); 145 158 } 159 + if (copy_to_user(p, &buf, sizeof(buf))) 160 + return -EFAULT; 146 161 return 0; 147 162 } 148 163 149 164 SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf) 150 165 { 151 - struct path path; 152 - int error; 153 - 154 - error = user_path(pathname, &path); 155 - if (!error) { 156 - struct statfs tmp; 157 - error = do_statfs_native(&path, &tmp); 158 - if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 159 - error = -EFAULT; 160 - path_put(&path); 161 - } 166 + struct kstatfs st; 167 + int error = user_statfs(pathname, &st); 168 + if (!error) 169 + error = do_statfs_native(&st, buf); 162 170 return error; 163 171 } 164 172 165 173 SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf) 166 174 { 167 - struct path path; 168 - long error; 169 - 175 + struct kstatfs st; 176 + int error; 170 177 if (sz != sizeof(*buf)) 171 178 return -EINVAL; 172 - error = user_path(pathname, &path); 173 - if (!error) { 174 - struct statfs64 tmp; 175 - error = do_statfs64(&path, &tmp); 176 - if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 177 - error = -EFAULT; 178 - path_put(&path); 179 - } 179 + error = user_statfs(pathname, &st); 180 + if (!error) 181 + error = do_statfs64(&st, buf); 180 182 return error; 181 183 } 182 184 183 185 SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf) 184 186 { 185 - struct file *file; 186 - struct statfs tmp; 187 - int error; 188 - 189 - error = -EBADF; 190 - file = fget(fd); 191 - if (!file) 192 - goto out; 193 - error = do_statfs_native(&file->f_path, &tmp); 194 - if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 195 - error = -EFAULT; 196 - fput(file); 197 - out: 187 + struct kstatfs st; 188 + int error = fd_statfs(fd, &st); 189 + if (!error) 190 + error = do_statfs_native(&st, buf); 198 191 return error; 199 192 } 200 193 201 194 SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf) 202 195 { 203 - struct file *file; 204 - struct statfs64 tmp; 196 + struct kstatfs st; 205 197 int error; 206 198 207 199 if (sz != sizeof(*buf)) 208 200 return -EINVAL; 209 201 210 - error = -EBADF; 211 - file = fget(fd); 212 - if (!file) 213 - goto out; 214 - error = do_statfs64(&file->f_path, &tmp); 215 - if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 216 - error = -EFAULT; 217 - fput(file); 218 - out: 202 + error = fd_statfs(fd, &st); 203 + if (!error) 204 + error = do_statfs64(&st, buf); 219 205 return error; 220 206 } 221 207
+2
include/linux/fs.h
··· 1874 1874 extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *, 1875 1875 struct vfsmount *); 1876 1876 extern int vfs_statfs(struct path *, struct kstatfs *); 1877 + extern int user_statfs(const char __user *, struct kstatfs *); 1878 + extern int fd_statfs(int, struct kstatfs *); 1877 1879 extern int statfs_by_dentry(struct dentry *, struct kstatfs *); 1878 1880 extern int freeze_super(struct super_block *super); 1879 1881 extern int thaw_super(struct super_block *super);