perf env: Conditionally compile BPF support code on having HAVE_LIBBPF_SUPPORT
[linux-2.6-microblaze.git] / mm / filemap.c
index 1a6beaf..d5e7c20 100644 (file)
@@ -2199,6 +2199,14 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
        last_index = (*ppos + iter->count + PAGE_SIZE-1) >> PAGE_SHIFT;
        offset = *ppos & ~PAGE_MASK;
 
+       /*
+        * If we've already successfully copied some data, then we
+        * can no longer safely return -EIOCBQUEUED. Hence mark
+        * an async read NOWAIT at that point.
+        */
+       if (written && (iocb->ki_flags & IOCB_WAITQ))
+               iocb->ki_flags |= IOCB_NOWAIT;
+
        for (;;) {
                struct page *page;
                pgoff_t end_index;
@@ -3113,228 +3121,6 @@ struct page *read_cache_page_gfp(struct address_space *mapping,
 }
 EXPORT_SYMBOL(read_cache_page_gfp);
 
-/*
- * Don't operate on ranges the page cache doesn't support, and don't exceed the
- * LFS limits.  If pos is under the limit it becomes a short access.  If it
- * exceeds the limit we return -EFBIG.
- */
-static int generic_write_check_limits(struct file *file, loff_t pos,
-                                     loff_t *count)
-{
-       struct inode *inode = file->f_mapping->host;
-       loff_t max_size = inode->i_sb->s_maxbytes;
-       loff_t limit = rlimit(RLIMIT_FSIZE);
-
-       if (limit != RLIM_INFINITY) {
-               if (pos >= limit) {
-                       send_sig(SIGXFSZ, current, 0);
-                       return -EFBIG;
-               }
-               *count = min(*count, limit - pos);
-       }
-
-       if (!(file->f_flags & O_LARGEFILE))
-               max_size = MAX_NON_LFS;
-
-       if (unlikely(pos >= max_size))
-               return -EFBIG;
-
-       *count = min(*count, max_size - pos);
-
-       return 0;
-}
-
-/*
- * Performs necessary checks before doing a write
- *
- * Can adjust writing position or amount of bytes to write.
- * Returns appropriate error code that caller should return or
- * zero in case that write should be allowed.
- */
-inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
-{
-       struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_mapping->host;
-       loff_t count;
-       int ret;
-
-       if (IS_SWAPFILE(inode))
-               return -ETXTBSY;
-
-       if (!iov_iter_count(from))
-               return 0;
-
-       /* FIXME: this is for backwards compatibility with 2.4 */
-       if (iocb->ki_flags & IOCB_APPEND)
-               iocb->ki_pos = i_size_read(inode);
-
-       if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
-               return -EINVAL;
-
-       count = iov_iter_count(from);
-       ret = generic_write_check_limits(file, iocb->ki_pos, &count);
-       if (ret)
-               return ret;
-
-       iov_iter_truncate(from, count);
-       return iov_iter_count(from);
-}
-EXPORT_SYMBOL(generic_write_checks);
-
-/*
- * Performs necessary checks before doing a clone.
- *
- * Can adjust amount of bytes to clone via @req_count argument.
- * Returns appropriate error code that caller should return or
- * zero in case the clone should be allowed.
- */
-int generic_remap_checks(struct file *file_in, loff_t pos_in,
-                        struct file *file_out, loff_t pos_out,
-                        loff_t *req_count, unsigned int remap_flags)
-{
-       struct inode *inode_in = file_in->f_mapping->host;
-       struct inode *inode_out = file_out->f_mapping->host;
-       uint64_t count = *req_count;
-       uint64_t bcount;
-       loff_t size_in, size_out;
-       loff_t bs = inode_out->i_sb->s_blocksize;
-       int ret;
-
-       /* The start of both ranges must be aligned to an fs block. */
-       if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_out, bs))
-               return -EINVAL;
-
-       /* Ensure offsets don't wrap. */
-       if (pos_in + count < pos_in || pos_out + count < pos_out)
-               return -EINVAL;
-
-       size_in = i_size_read(inode_in);
-       size_out = i_size_read(inode_out);
-
-       /* Dedupe requires both ranges to be within EOF. */
-       if ((remap_flags & REMAP_FILE_DEDUP) &&
-           (pos_in >= size_in || pos_in + count > size_in ||
-            pos_out >= size_out || pos_out + count > size_out))
-               return -EINVAL;
-
-       /* Ensure the infile range is within the infile. */
-       if (pos_in >= size_in)
-               return -EINVAL;
-       count = min(count, size_in - (uint64_t)pos_in);
-
-       ret = generic_write_check_limits(file_out, pos_out, &count);
-       if (ret)
-               return ret;
-
-       /*
-        * If the user wanted us to link to the infile's EOF, round up to the
-        * next block boundary for this check.
-        *
-        * Otherwise, make sure the count is also block-aligned, having
-        * already confirmed the starting offsets' block alignment.
-        */
-       if (pos_in + count == size_in) {
-               bcount = ALIGN(size_in, bs) - pos_in;
-       } else {
-               if (!IS_ALIGNED(count, bs))
-                       count = ALIGN_DOWN(count, bs);
-               bcount = count;
-       }
-
-       /* Don't allow overlapped cloning within the same file. */
-       if (inode_in == inode_out &&
-           pos_out + bcount > pos_in &&
-           pos_out < pos_in + bcount)
-               return -EINVAL;
-
-       /*
-        * We shortened the request but the caller can't deal with that, so
-        * bounce the request back to userspace.
-        */
-       if (*req_count != count && !(remap_flags & REMAP_FILE_CAN_SHORTEN))
-               return -EINVAL;
-
-       *req_count = count;
-       return 0;
-}
-
-
-/*
- * Performs common checks before doing a file copy/clone
- * from @file_in to @file_out.
- */
-int generic_file_rw_checks(struct file *file_in, struct file *file_out)
-{
-       struct inode *inode_in = file_inode(file_in);
-       struct inode *inode_out = file_inode(file_out);
-
-       /* Don't copy dirs, pipes, sockets... */
-       if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
-               return -EISDIR;
-       if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
-               return -EINVAL;
-
-       if (!(file_in->f_mode & FMODE_READ) ||
-           !(file_out->f_mode & FMODE_WRITE) ||
-           (file_out->f_flags & O_APPEND))
-               return -EBADF;
-
-       return 0;
-}
-
-/*
- * Performs necessary checks before doing a file copy
- *
- * Can adjust amount of bytes to copy via @req_count argument.
- * Returns appropriate error code that caller should return or
- * zero in case the copy should be allowed.
- */
-int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
-                            struct file *file_out, loff_t pos_out,
-                            size_t *req_count, unsigned int flags)
-{
-       struct inode *inode_in = file_inode(file_in);
-       struct inode *inode_out = file_inode(file_out);
-       uint64_t count = *req_count;
-       loff_t size_in;
-       int ret;
-
-       ret = generic_file_rw_checks(file_in, file_out);
-       if (ret)
-               return ret;
-
-       /* Don't touch certain kinds of inodes */
-       if (IS_IMMUTABLE(inode_out))
-               return -EPERM;
-
-       if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out))
-               return -ETXTBSY;
-
-       /* Ensure offsets don't wrap. */
-       if (pos_in + count < pos_in || pos_out + count < pos_out)
-               return -EOVERFLOW;
-
-       /* Shorten the copy to EOF */
-       size_in = i_size_read(inode_in);
-       if (pos_in >= size_in)
-               count = 0;
-       else
-               count = min(count, size_in - (uint64_t)pos_in);
-
-       ret = generic_write_check_limits(file_out, pos_out, &count);
-       if (ret)
-               return ret;
-
-       /* Don't allow overlapped copying within the same file. */
-       if (inode_in == inode_out &&
-           pos_out + count > pos_in &&
-           pos_out < pos_in + count)
-               return -EINVAL;
-
-       *req_count = count;
-       return 0;
-}
-
 int pagecache_write_begin(struct file *file, struct address_space *mapping,
                                loff_t pos, unsigned len, unsigned flags,
                                struct page **pagep, void **fsdata)