Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[cascardo/linux.git] / fs / gfs2 / file.c
index 08329af..3189287 100644 (file)
@@ -428,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;
@@ -764,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;
@@ -796,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;
@@ -818,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;
@@ -826,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);
@@ -930,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
 
 /**
@@ -1074,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,
 };
@@ -1102,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,
 };