mm: kill vma flag VM_CAN_NONLINEAR
[linux-3.10.git] / fs / gfs2 / file.c
index 26e2905..0def050 100644 (file)
@@ -142,6 +142,7 @@ static const u32 fsflags_to_gfs2[32] = {
        [7] = GFS2_DIF_NOATIME,
        [12] = GFS2_DIF_EXHASH,
        [14] = GFS2_DIF_INHERIT_JDATA,
+       [17] = GFS2_DIF_TOPDIR,
 };
 
 static const u32 gfs2_to_fsflags[32] = {
@@ -150,6 +151,7 @@ static const u32 gfs2_to_fsflags[32] = {
        [gfs2fl_AppendOnly] = FS_APPEND_FL,
        [gfs2fl_NoAtime] = FS_NOATIME_FL,
        [gfs2fl_ExHash] = FS_INDEX_FL,
+       [gfs2fl_TopLevel] = FS_TOPDIR_FL,
        [gfs2fl_InheritJdata] = FS_JOURNAL_DATA_FL,
 };
 
@@ -203,6 +205,7 @@ void gfs2_set_inode_flags(struct inode *inode)
                             GFS2_DIF_NOATIME|                  \
                             GFS2_DIF_SYNC|                     \
                             GFS2_DIF_SYSTEM|                   \
+                            GFS2_DIF_TOPDIR|                   \
                             GFS2_DIF_INHERIT_JDATA)
 
 /**
@@ -298,6 +301,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
 
        gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags);
        if (!S_ISDIR(inode->i_mode)) {
+               gfsflags &= ~GFS2_DIF_TOPDIR;
                if (gfsflags & GFS2_DIF_INHERIT_JDATA)
                        gfsflags ^= (GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA);
                return do_gfs2_set_flags(filp, gfsflags, ~0);
@@ -319,6 +323,29 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 }
 
 /**
+ * gfs2_size_hint - Give a hint to the size of a write request
+ * @file: The struct file
+ * @offset: The file offset of the write
+ * @size: The length of the write
+ *
+ * When we are about to do a write, this function records the total
+ * write size in order to provide a suitable hint to the lower layers
+ * about how many blocks will be required.
+ *
+ */
+
+static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size)
+{
+       struct inode *inode = filep->f_dentry->d_inode;
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct gfs2_inode *ip = GFS2_I(inode);
+       size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift;
+       int hint = min_t(size_t, INT_MAX, blks);
+
+       atomic_set(&ip->i_res->rs_sizehint, hint);
+}
+
+/**
  * gfs2_allocate_page_backing - Use bmap to allocate blocks
  * @page: The (locked) page to allocate backing for
  *
@@ -369,16 +396,17 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        loff_t size;
        int ret;
 
-       /* Wait if fs is frozen. This is racy so we check again later on
-        * and retry if the fs has been frozen after the page lock has
-        * been acquired
-        */
-       vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+       sb_start_pagefault(inode->i_sb);
+
+       /* Update file times before taking page lock */
+       file_update_time(vma->vm_file);
 
        ret = gfs2_rs_alloc(ip);
        if (ret)
                return ret;
 
+       gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);
+
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret)
@@ -413,7 +441,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
                rblocks += data_blocks ? data_blocks : 1;
        if (ind_blocks || data_blocks) {
                rblocks += RES_STATFS + RES_QUOTA;
-               rblocks += gfs2_rg_blocks(ip);
+               rblocks += gfs2_rg_blocks(ip, data_blocks + ind_blocks);
        }
        ret = gfs2_trans_begin(sdp, rblocks, 0);
        if (ret)
@@ -455,20 +483,16 @@ out:
        gfs2_holder_uninit(&gh);
        if (ret == 0) {
                set_page_dirty(page);
-               /* This check must be post dropping of transaction lock */
-               if (inode->i_sb->s_frozen == SB_UNFROZEN) {
-                       wait_on_page_writeback(page);
-               } else {
-                       ret = -EAGAIN;
-                       unlock_page(page);
-               }
+               wait_on_page_writeback(page);
        }
+       sb_end_pagefault(inode->i_sb);
        return block_page_mkwrite_return(ret);
 }
 
 static const struct vm_operations_struct gfs2_vm_ops = {
        .fault = filemap_fault,
        .page_mkwrite = gfs2_page_mkwrite,
+       .remap_pages = generic_file_remap_pages,
 };
 
 /**
@@ -503,7 +527,6 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
                        return error;
        }
        vma->vm_ops = &gfs2_vm_ops;
-       vma->vm_flags |= VM_CAN_NONLINEAR;
 
        return 0;
 }
@@ -567,22 +590,15 @@ fail:
 
 static int gfs2_release(struct inode *inode, struct file *file)
 {
-       struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
-       struct gfs2_file *fp;
        struct gfs2_inode *ip = GFS2_I(inode);
 
-       fp = file->private_data;
+       kfree(file->private_data);
        file->private_data = NULL;
 
-       if ((file->f_mode & FMODE_WRITE) && ip->i_res &&
+       if ((file->f_mode & FMODE_WRITE) &&
            (atomic_read(&inode->i_writecount) == 1))
                gfs2_rs_delete(ip);
 
-       if (gfs2_assert_warn(sdp, fp))
-               return -EIO;
-
-       kfree(fp);
-
        return 0;
 }
 
@@ -658,14 +674,19 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                   unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
+       size_t writesize = iov_length(iov, nr_segs);
        struct dentry *dentry = file->f_dentry;
        struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
+       struct gfs2_sbd *sdp;
        int ret;
 
+       sdp = GFS2_SB(file->f_mapping->host);
        ret = gfs2_rs_alloc(ip);
        if (ret)
                return ret;
 
+       gfs2_size_hint(file, pos, writesize);
+
        if (file->f_flags & O_APPEND) {
                struct gfs2_holder gh;
 
@@ -791,6 +812,8 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
        if (unlikely(error))
                goto out_uninit;
 
+       gfs2_size_hint(file, offset, len);
+
        while (len > 0) {
                if (len < bytes)
                        bytes = len;
@@ -799,10 +822,6 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
                        offset += bytes;
                        continue;
                }
-               error = gfs2_rindex_update(sdp);
-               if (error)
-                       goto out_unlock;
-
                error = gfs2_quota_lock_check(ip);
                if (error)
                        goto out_unlock;
@@ -826,7 +845,7 @@ retry:
                                &max_bytes, &data_blocks, &ind_blocks);
 
                rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA +
-                         RES_RG_HDR + gfs2_rg_blocks(ip);
+                         RES_RG_HDR + gfs2_rg_blocks(ip, data_blocks + ind_blocks);
                if (gfs2_is_jdata(ip))
                        rblocks += data_blocks ? data_blocks : 1;