]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/gfs2/ops_inode.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / fs / gfs2 / ops_inode.c
index 12cbea7502c26040fb90db5750e764bdd831079a..d8b26ac2e20be7c7fe7b91b136c69e3e319a531b 100644 (file)
@@ -18,8 +18,6 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/fiemap.h>
-#include <linux/swap.h>
-#include <linux/falloc.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
@@ -106,8 +104,6 @@ static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
 {
        struct inode *inode = NULL;
 
-       dentry->d_op = &gfs2_dops;
-
        inode = gfs2_lookupi(dir, &dentry->d_name, 0);
        if (inode && IS_ERR(inode))
                return ERR_CAST(inode);
@@ -166,7 +162,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
        if (error)
                goto out_child;
 
-       error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC);
+       error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0);
        if (error)
                goto out_gunlock;
 
@@ -289,7 +285,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
        if (IS_APPEND(&dip->i_inode))
                return -EPERM;
 
-       error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC);
+       error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0);
        if (error)
                return error;
 
@@ -822,7 +818,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                        }
                }
        } else {
-               error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC);
+               error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC, 0);
                if (error)
                        goto out_gunlock;
 
@@ -857,7 +853,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        /* Check out the dir to be renamed */
 
        if (dir_rename) {
-               error = gfs2_permission(odentry->d_inode, MAY_WRITE);
+               error = gfs2_permission(odentry->d_inode, MAY_WRITE, 0);
                if (error)
                        goto out_gunlock;
        }
@@ -1041,13 +1037,17 @@ static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
  * Returns: errno
  */
 
-int gfs2_permission(struct inode *inode, int mask)
+int gfs2_permission(struct inode *inode, int mask, unsigned int flags)
 {
-       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_inode *ip;
        struct gfs2_holder i_gh;
        int error;
        int unlock = 0;
 
+       if (flags & IPERM_FLAG_RCU)
+               return -ECHILD;
+
+       ip = GFS2_I(inode);
        if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
                error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
                if (error)
@@ -1058,7 +1058,7 @@ int gfs2_permission(struct inode *inode, int mask)
        if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
                error = -EACCES;
        else
-               error = generic_permission(inode, mask, gfs2_check_acl);
+               error = generic_permission(inode, mask, flags, gfs2_check_acl);
        if (unlock)
                gfs2_glock_dq_uninit(&i_gh);
 
@@ -1069,7 +1069,6 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
-       struct buffer_head *dibh;
        u32 ouid, ogid, nuid, ngid;
        int error;
 
@@ -1100,25 +1099,10 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
        if (error)
                goto out_gunlock_q;
 
-       error = gfs2_meta_inode_buffer(ip, &dibh);
+       error = gfs2_setattr_simple(ip, attr);
        if (error)
                goto out_end_trans;
 
-       if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode)) {
-               int error;
-
-               error = vmtruncate(inode, attr->ia_size);
-               gfs2_assert_warn(sdp, !error);
-       }
-
-       setattr_copy(inode, attr);
-       mark_inode_dirty(inode);
-
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_dinode_out(ip, dibh->b_data);
-       brelse(dibh);
-
        if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
                u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
                gfs2_quota_change(ip, -blocks, ouid, ogid);
@@ -1271,257 +1255,6 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
        return ret;
 }
 
-static void empty_write_end(struct page *page, unsigned from,
-                          unsigned to)
-{
-       struct gfs2_inode *ip = GFS2_I(page->mapping->host);
-
-       page_zero_new_buffers(page, from, to);
-       flush_dcache_page(page);
-       mark_page_accessed(page);
-
-       if (!gfs2_is_writeback(ip))
-               gfs2_page_add_databufs(ip, page, from, to);
-
-       block_commit_write(page, from, to);
-}
-
-
-static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
-{
-       unsigned start, end, next;
-       struct buffer_head *bh, *head;
-       int error;
-
-       if (!page_has_buffers(page)) {
-               error = __block_write_begin(page, from, to - from, gfs2_block_map);
-               if (unlikely(error))
-                       return error;
-
-               empty_write_end(page, from, to);
-               return 0;
-       }
-
-       bh = head = page_buffers(page);
-       next = end = 0;
-       while (next < from) {
-               next += bh->b_size;
-               bh = bh->b_this_page;
-       }
-       start = next;
-       do {
-               next += bh->b_size;
-               if (buffer_mapped(bh)) {
-                       if (end) {
-                               error = __block_write_begin(page, start, end - start,
-                                                           gfs2_block_map);
-                               if (unlikely(error))
-                                       return error;
-                               empty_write_end(page, start, end);
-                               end = 0;
-                       }
-                       start = next;
-               }
-               else
-                       end = next;
-               bh = bh->b_this_page;
-       } while (next < to);
-
-       if (end) {
-               error = __block_write_begin(page, start, end - start, gfs2_block_map);
-               if (unlikely(error))
-                       return error;
-               empty_write_end(page, start, end);
-       }
-
-       return 0;
-}
-
-static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
-                          int mode)
-{
-       struct gfs2_inode *ip = GFS2_I(inode);
-       struct buffer_head *dibh;
-       int error;
-       u64 start = offset >> PAGE_CACHE_SHIFT;
-       unsigned int start_offset = offset & ~PAGE_CACHE_MASK;
-       u64 end = (offset + len - 1) >> PAGE_CACHE_SHIFT;
-       pgoff_t curr;
-       struct page *page;
-       unsigned int end_offset = (offset + len) & ~PAGE_CACHE_MASK;
-       unsigned int from, to;
-
-       if (!end_offset)
-               end_offset = PAGE_CACHE_SIZE;
-
-       error = gfs2_meta_inode_buffer(ip, &dibh);
-       if (unlikely(error))
-               goto out;
-
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-
-       if (gfs2_is_stuffed(ip)) {
-               error = gfs2_unstuff_dinode(ip, NULL);
-               if (unlikely(error))
-                       goto out;
-       }
-
-       curr = start;
-       offset = start << PAGE_CACHE_SHIFT;
-       from = start_offset;
-       to = PAGE_CACHE_SIZE;
-       while (curr <= end) {
-               page = grab_cache_page_write_begin(inode->i_mapping, curr,
-                                                  AOP_FLAG_NOFS);
-               if (unlikely(!page)) {
-                       error = -ENOMEM;
-                       goto out;
-               }
-
-               if (curr == end)
-                       to = end_offset;
-               error = write_empty_blocks(page, from, to);
-               if (!error && offset + to > inode->i_size &&
-                   !(mode & FALLOC_FL_KEEP_SIZE)) {
-                       i_size_write(inode, offset + to);
-               }
-               unlock_page(page);
-               page_cache_release(page);
-               if (error)
-                       goto out;
-               curr++;
-               offset += PAGE_CACHE_SIZE;
-               from = 0;
-       }
-
-       gfs2_dinode_out(ip, dibh->b_data);
-       mark_inode_dirty(inode);
-
-       brelse(dibh);
-
-out:
-       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)
-{
-       const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       unsigned int max_blocks = ip->i_alloc->al_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;
-       if (*len > max) {
-               *len = max;
-               gfs2_write_calc_reserv(ip, max, data_blocks, ind_blocks);
-       }
-}
-
-static long gfs2_fallocate(struct inode *inode, int mode, loff_t offset,
-                          loff_t len)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(inode);
-       struct gfs2_inode *ip = GFS2_I(inode);
-       unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
-       loff_t bytes, max_bytes;
-       struct gfs2_alloc *al;
-       int error;
-       loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift;
-       next = (next + 1) << sdp->sd_sb.sb_bsize_shift;
-
-       offset = (offset >> sdp->sd_sb.sb_bsize_shift) <<
-                sdp->sd_sb.sb_bsize_shift;
-
-       len = next - offset;
-       bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2;
-       if (!bytes)
-               bytes = UINT_MAX;
-
-       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;
-
-       if (!gfs2_write_alloc_required(ip, offset, len))
-               goto out_unlock;
-
-       while (len > 0) {
-               if (len < bytes)
-                       bytes = len;
-               al = gfs2_alloc_get(ip);
-               if (!al) {
-                       error = -ENOMEM;
-                       goto out_unlock;
-               }
-
-               error = gfs2_quota_lock_check(ip);
-               if (error)
-                       goto out_alloc_put;
-
-retry:
-               gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
-
-               al->al_requested = data_blocks + ind_blocks;
-               error = gfs2_inplace_reserve(ip);
-               if (error) {
-                       if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
-                               bytes >>= 1;
-                               goto retry;
-                       }
-                       goto out_qunlock;
-               }
-               max_bytes = bytes;
-               calc_max_reserv(ip, len, &max_bytes, &data_blocks, &ind_blocks);
-               al->al_requested = data_blocks + ind_blocks;
-
-               rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA +
-                         RES_RG_HDR + gfs2_rg_blocks(al);
-               if (gfs2_is_jdata(ip))
-                       rblocks += data_blocks ? data_blocks : 1;
-
-               error = gfs2_trans_begin(sdp, rblocks,
-                                        PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
-               if (error)
-                       goto out_trans_fail;
-
-               error = fallocate_chunk(inode, offset, max_bytes, mode);
-               gfs2_trans_end(sdp);
-
-               if (error)
-                       goto out_trans_fail;
-
-               len -= max_bytes;
-               offset += max_bytes;
-               gfs2_inplace_release(ip);
-               gfs2_quota_unlock(ip);
-               gfs2_alloc_put(ip);
-       }
-       goto out_unlock;
-
-out_trans_fail:
-       gfs2_inplace_release(ip);
-out_qunlock:
-       gfs2_quota_unlock(ip);
-out_alloc_put:
-       gfs2_alloc_put(ip);
-out_unlock:
-       gfs2_glock_dq(&ip->i_gh);
-out_uninit:
-       gfs2_holder_uninit(&ip->i_gh);
-       return error;
-}
-
-
 static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                       u64 start, u64 len)
 {
@@ -1572,7 +1305,6 @@ const struct inode_operations gfs2_file_iops = {
        .getxattr = gfs2_getxattr,
        .listxattr = gfs2_listxattr,
        .removexattr = gfs2_removexattr,
-       .fallocate = gfs2_fallocate,
        .fiemap = gfs2_fiemap,
 };