Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-drm-fsl-dcu.git] / fs / gfs2 / file.c
index 8ffeb031248e0b26799eba6b16dda84fe94f3cf6..d1d791ef38de2188852551254a63f974a605feff 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);
@@ -366,7 +370,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        u64 pos = page->index << PAGE_CACHE_SHIFT;
        unsigned int data_blocks, ind_blocks, rblocks;
        struct gfs2_holder gh;
-       struct gfs2_qadata *qa;
        loff_t size;
        int ret;
 
@@ -375,6 +378,13 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        /* Update file times before taking page lock */
        file_update_time(vma->vm_file);
 
+       ret = gfs2_rs_alloc(ip);
+       if (ret)
+               return ret;
+
+       atomic_set(&ip->i_res->rs_sizehint,
+                  PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift);
+
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret)
@@ -392,14 +402,13 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
                goto out_unlock;
        }
 
-       ret = -ENOMEM;
-       qa = gfs2_qadata_get(ip);
-       if (qa == NULL)
+       ret = gfs2_rindex_update(sdp);
+       if (ret)
                goto out_unlock;
 
        ret = gfs2_quota_lock_check(ip);
        if (ret)
-               goto out_alloc_put;
+               goto out_unlock;
        gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
        ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks);
        if (ret)
@@ -446,8 +455,6 @@ out_trans_fail:
        gfs2_inplace_release(ip);
 out_quota_unlock:
        gfs2_quota_unlock(ip);
-out_alloc_put:
-       gfs2_qadata_put(ip);
 out_unlock:
        gfs2_glock_dq(&gh);
 out:
@@ -561,16 +568,14 @@ 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 (gfs2_assert_warn(sdp, fp))
-               return -EIO;
-
-       kfree(fp);
+       if ((file->f_mode & FMODE_WRITE) &&
+           (atomic_read(&inode->i_writecount) == 1))
+               gfs2_rs_delete(ip);
 
        return 0;
 }
@@ -647,12 +652,20 @@ 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;
+
+       atomic_set(&ip->i_res->rs_sizehint, writesize >> sdp->sd_sb.sb_bsize_shift);
        if (file->f_flags & O_APPEND) {
-               struct dentry *dentry = file->f_dentry;
-               struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
                struct gfs2_holder gh;
-               int ret;
 
                ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
                if (ret)
@@ -745,7 +758,6 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
        struct gfs2_inode *ip = GFS2_I(inode);
        unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
        loff_t bytes, max_bytes;
-       struct gfs2_qadata *qa;
        int error;
        const loff_t pos = offset;
        const loff_t count = len;
@@ -768,11 +780,17 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
        if (bytes == 0)
                bytes = sdp->sd_sb.sb_bsize;
 
+       error = gfs2_rs_alloc(ip);
+       if (error)
+               return error;
+
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
        error = gfs2_glock_nq(&ip->i_gh);
        if (unlikely(error))
                goto out_uninit;
 
+       atomic_set(&ip->i_res->rs_sizehint, len >> sdp->sd_sb.sb_bsize_shift);
+
        while (len > 0) {
                if (len < bytes)
                        bytes = len;
@@ -781,15 +799,9 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
                        offset += bytes;
                        continue;
                }
-               qa = gfs2_qadata_get(ip);
-               if (!qa) {
-                       error = -ENOMEM;
-                       goto out_unlock;
-               }
-
                error = gfs2_quota_lock_check(ip);
                if (error)
-                       goto out_alloc_put;
+                       goto out_unlock;
 
 retry:
                gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
@@ -829,7 +841,6 @@ retry:
                offset += max_bytes;
                gfs2_inplace_release(ip);
                gfs2_quota_unlock(ip);
-               gfs2_qadata_put(ip);
        }
 
        if (error == 0)
@@ -840,8 +851,6 @@ out_trans_fail:
        gfs2_inplace_release(ip);
 out_qunlock:
        gfs2_quota_unlock(ip);
-out_alloc_put:
-       gfs2_qadata_put(ip);
 out_unlock:
        gfs2_glock_dq(&ip->i_gh);
 out_uninit: