bna: make pointers to read-only inputs const
[cascardo/linux.git] / fs / gfs2 / file.c
index 3e32bb8..3189287 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <linux/dlm.h>
 #include <linux/dlm_plock.h>
-#include <linux/aio.h>
 #include <linux/delay.h>
 
 #include "gfs2.h"
@@ -429,11 +428,11 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        if (ret)
                goto out_unlock;
 
-       ret = gfs2_quota_lock_check(ip);
-       if (ret)
-               goto out_unlock;
        gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
        ap.target = data_blocks + ind_blocks;
+       ret = gfs2_quota_lock_check(ip, &ap);
+       if (ret)
+               goto out_unlock;
        ret = gfs2_inplace_reserve(ip, &ap);
        if (ret)
                goto out_quota_unlock;
@@ -710,7 +709,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 
        gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
 
-       if (file->f_flags & O_APPEND) {
+       if (iocb->ki_flags & IOCB_APPEND) {
                struct gfs2_holder gh;
 
                ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
@@ -765,22 +764,30 @@ out:
        brelse(dibh);
        return error;
 }
-
-static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len,
-                           unsigned int *data_blocks, unsigned int *ind_blocks)
+/**
+ * calc_max_reserv() - Reverse of write_calc_reserv. Given a number of
+ *                     blocks, determine how many bytes can be written.
+ * @ip:          The inode in question.
+ * @len:         Max cap of bytes. What we return in *len must be <= this.
+ * @data_blocks: Compute and return the number of data blocks needed
+ * @ind_blocks:  Compute and return the number of indirect blocks needed
+ * @max_blocks:  The total blocks available to work with.
+ *
+ * Returns: void, but @len, @data_blocks and @ind_blocks are filled in.
+ */
+static void calc_max_reserv(struct gfs2_inode *ip, loff_t *len,
+                           unsigned int *data_blocks, unsigned int *ind_blocks,
+                           unsigned int max_blocks)
 {
+       loff_t max = *len;
        const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       unsigned int max_blocks = ip->i_rgd->rd_free_clone;
        unsigned int tmp, max_data = max_blocks - 3 * (sdp->sd_max_height - 1);
 
        for (tmp = max_data; tmp > sdp->sd_diptrs;) {
                tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs);
                max_data -= tmp;
        }
-       /* This calculation isn't the exact reverse of gfs2_write_calc_reserve,
-          so it might end up with fewer data blocks */
-       if (max_data <= *data_blocks)
-               return;
+
        *data_blocks = max_data;
        *ind_blocks = max_blocks - max_data;
        *len = ((loff_t)max_data - 3) << sdp->sd_sb.sb_bsize_shift;
@@ -797,7 +804,7 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_alloc_parms ap = { .aflags = 0, };
        unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
-       loff_t bytes, max_bytes;
+       loff_t bytes, max_bytes, max_blks = UINT_MAX;
        int error;
        const loff_t pos = offset;
        const loff_t count = len;
@@ -819,6 +826,9 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
 
        gfs2_size_hint(file, offset, len);
 
+       gfs2_write_calc_reserv(ip, PAGE_SIZE, &data_blocks, &ind_blocks);
+       ap.min_target = data_blocks + ind_blocks;
+
        while (len > 0) {
                if (len < bytes)
                        bytes = len;
@@ -827,27 +837,41 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
                        offset += bytes;
                        continue;
                }
-               error = gfs2_quota_lock_check(ip);
+
+               /* We need to determine how many bytes we can actually
+                * fallocate without exceeding quota or going over the
+                * end of the fs. We start off optimistically by assuming
+                * we can write max_bytes */
+               max_bytes = (len > max_chunk_size) ? max_chunk_size : len;
+
+               /* Since max_bytes is most likely a theoretical max, we
+                * calculate a more realistic 'bytes' to serve as a good
+                * starting point for the number of bytes we may be able
+                * to write */
+               gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
+               ap.target = data_blocks + ind_blocks;
+
+               error = gfs2_quota_lock_check(ip, &ap);
                if (error)
                        return error;
-retry:
-               gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
+               /* ap.allowed tells us how many blocks quota will allow
+                * us to write. Check if this reduces max_blks */
+               if (ap.allowed && ap.allowed < max_blks)
+                       max_blks = ap.allowed;
 
-               ap.target = data_blocks + ind_blocks;
                error = gfs2_inplace_reserve(ip, &ap);
-               if (error) {
-                       if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
-                               bytes >>= 1;
-                               bytes &= bsize_mask;
-                               if (bytes == 0)
-                                       bytes = sdp->sd_sb.sb_bsize;
-                               goto retry;
-                       }
+               if (error)
                        goto out_qunlock;
-               }
-               max_bytes = bytes;
-               calc_max_reserv(ip, (len > max_chunk_size)? max_chunk_size: len,
-                               &max_bytes, &data_blocks, &ind_blocks);
+
+               /* check if the selected rgrp limits our max_blks further */
+               if (ap.allowed && ap.allowed < max_blks)
+                       max_blks = ap.allowed;
+
+               /* Almost done. Calculate bytes that can be written using
+                * max_blks. We also recompute max_bytes, data_blocks and
+                * ind_blocks */
+               calc_max_reserv(ip, &max_bytes, &data_blocks,
+                               &ind_blocks, max_blks);
 
                rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA +
                          RES_RG_HDR + gfs2_rg_blocks(ip, data_blocks + ind_blocks);
@@ -931,6 +955,22 @@ out_uninit:
        return ret;
 }
 
+static ssize_t gfs2_file_splice_write(struct pipe_inode_info *pipe,
+                                     struct file *out, loff_t *ppos,
+                                     size_t len, unsigned int flags)
+{
+       int error;
+       struct gfs2_inode *ip = GFS2_I(out->f_mapping->host);
+
+       error = gfs2_rs_alloc(ip);
+       if (error)
+               return (ssize_t)error;
+
+       gfs2_size_hint(out, *ppos, len);
+
+       return iter_file_splice_write(pipe, out, ppos, len, flags);
+}
+
 #ifdef CONFIG_GFS2_FS_LOCKING_DLM
 
 /**
@@ -1065,9 +1105,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
 
 const struct file_operations gfs2_file_fops = {
        .llseek         = gfs2_llseek,
-       .read           = new_sync_read,
        .read_iter      = generic_file_read_iter,
-       .write          = new_sync_write,
        .write_iter     = gfs2_file_write_iter,
        .unlocked_ioctl = gfs2_ioctl,
        .mmap           = gfs2_mmap,
@@ -1077,7 +1115,7 @@ const struct file_operations gfs2_file_fops = {
        .lock           = gfs2_lock,
        .flock          = gfs2_flock,
        .splice_read    = generic_file_splice_read,
-       .splice_write   = iter_file_splice_write,
+       .splice_write   = gfs2_file_splice_write,
        .setlease       = simple_nosetlease,
        .fallocate      = gfs2_fallocate,
 };
@@ -1097,9 +1135,7 @@ const struct file_operations gfs2_dir_fops = {
 
 const struct file_operations gfs2_file_fops_nolock = {
        .llseek         = gfs2_llseek,
-       .read           = new_sync_read,
        .read_iter      = generic_file_read_iter,
-       .write          = new_sync_write,
        .write_iter     = gfs2_file_write_iter,
        .unlocked_ioctl = gfs2_ioctl,
        .mmap           = gfs2_mmap,
@@ -1107,7 +1143,7 @@ const struct file_operations gfs2_file_fops_nolock = {
        .release        = gfs2_release,
        .fsync          = gfs2_fsync,
        .splice_read    = generic_file_splice_read,
-       .splice_write   = iter_file_splice_write,
+       .splice_write   = gfs2_file_splice_write,
        .setlease       = generic_setlease,
        .fallocate      = gfs2_fallocate,
 };