aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c73
1 files changed, 70 insertions, 3 deletions
diff --git a/fs/open.c b/fs/open.c
index 0d515d161974..a6b054edacba 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -26,6 +26,7 @@
26#include <linux/syscalls.h> 26#include <linux/syscalls.h>
27#include <linux/rcupdate.h> 27#include <linux/rcupdate.h>
28#include <linux/audit.h> 28#include <linux/audit.h>
29#include <linux/falloc.h>
29 30
30int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) 31int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
31{ 32{
@@ -352,6 +353,64 @@ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
352} 353}
353#endif 354#endif
354 355
356asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len)
357{
358 struct file *file;
359 struct inode *inode;
360 long ret = -EINVAL;
361
362 if (offset < 0 || len <= 0)
363 goto out;
364
365 /* Return error if mode is not supported */
366 ret = -EOPNOTSUPP;
367 if (mode && !(mode & FALLOC_FL_KEEP_SIZE))
368 goto out;
369
370 ret = -EBADF;
371 file = fget(fd);
372 if (!file)
373 goto out;
374 if (!(file->f_mode & FMODE_WRITE))
375 goto out_fput;
376 /*
377 * Revalidate the write permissions, in case security policy has
378 * changed since the files were opened.
379 */
380 ret = security_file_permission(file, MAY_WRITE);
381 if (ret)
382 goto out_fput;
383
384 inode = file->f_path.dentry->d_inode;
385
386 ret = -ESPIPE;
387 if (S_ISFIFO(inode->i_mode))
388 goto out_fput;
389
390 ret = -ENODEV;
391 /*
392 * Let individual file system decide if it supports preallocation
393 * for directories or not.
394 */
395 if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
396 goto out_fput;
397
398 ret = -EFBIG;
399 /* Check for wrap through zero too */
400 if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
401 goto out_fput;
402
403 if (inode->i_op && inode->i_op->fallocate)
404 ret = inode->i_op->fallocate(inode, mode, offset, len);
405 else
406 ret = -ENOSYS;
407
408out_fput:
409 fput(file);
410out:
411 return ret;
412}
413
355/* 414/*
356 * access() needs to use the real uid/gid, not the effective uid/gid. 415 * access() needs to use the real uid/gid, not the effective uid/gid.
357 * We do this by temporarily clearing all FS-related capabilities and 416 * We do this by temporarily clearing all FS-related capabilities and
@@ -855,7 +914,7 @@ EXPORT_SYMBOL(dentry_open);
855/* 914/*
856 * Find an empty file descriptor entry, and mark it busy. 915 * Find an empty file descriptor entry, and mark it busy.
857 */ 916 */
858int get_unused_fd(void) 917int get_unused_fd_flags(int flags)
859{ 918{
860 struct files_struct * files = current->files; 919 struct files_struct * files = current->files;
861 int fd, error; 920 int fd, error;
@@ -891,7 +950,10 @@ repeat:
891 } 950 }
892 951
893 FD_SET(fd, fdt->open_fds); 952 FD_SET(fd, fdt->open_fds);
894 FD_CLR(fd, fdt->close_on_exec); 953 if (flags & O_CLOEXEC)
954 FD_SET(fd, fdt->close_on_exec);
955 else
956 FD_CLR(fd, fdt->close_on_exec);
895 files->next_fd = fd + 1; 957 files->next_fd = fd + 1;
896#if 1 958#if 1
897 /* Sanity check */ 959 /* Sanity check */
@@ -907,6 +969,11 @@ out:
907 return error; 969 return error;
908} 970}
909 971
972int get_unused_fd(void)
973{
974 return get_unused_fd_flags(0);
975}
976
910EXPORT_SYMBOL(get_unused_fd); 977EXPORT_SYMBOL(get_unused_fd);
911 978
912static void __put_unused_fd(struct files_struct *files, unsigned int fd) 979static void __put_unused_fd(struct files_struct *files, unsigned int fd)
@@ -959,7 +1026,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
959 int fd = PTR_ERR(tmp); 1026 int fd = PTR_ERR(tmp);
960 1027
961 if (!IS_ERR(tmp)) { 1028 if (!IS_ERR(tmp)) {
962 fd = get_unused_fd(); 1029 fd = get_unused_fd_flags(flags);
963 if (fd >= 0) { 1030 if (fd >= 0) {
964 struct file *f = do_filp_open(dfd, tmp, flags, mode); 1031 struct file *f = do_filp_open(dfd, tmp, flags, mode);
965 if (IS_ERR(f)) { 1032 if (IS_ERR(f)) {