Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 May 2010 15:17:51 +0000 (08:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 May 2010 15:17:51 +0000 (08:17 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes:
  GFS2: Fix permissions checking for setflags ioctl()
  GFS2: Don't "get" xattrs for ACLs when ACLs are turned off
  GFS2: Rework reclaiming unlinked dinodes

fs/gfs2/acl.c
fs/gfs2/file.c
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/log.c
fs/gfs2/log.h
fs/gfs2/rgrp.c

index 9fb76b0a048507c2450e0b8468bd34baf54c6db4..48171f4c943dbb2523a22011a25aca402fe3e6e5 100644 (file)
@@ -236,10 +236,14 @@ static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
                                 void *buffer, size_t size, int xtype)
 {
        struct inode *inode = dentry->d_inode;
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct posix_acl *acl;
        int type;
        int error;
 
+       if (!sdp->sd_args.ar_posix_acl)
+               return -EOPNOTSUPP;
+
        type = gfs2_acl_type(name);
        if (type < 0)
                return type;
index e6dd2aec6f822fe1ffa6cc8d442bd1dd03ca496f..b20bfcc9fa2d18bf09f3ef66745dfedb16d7bcdf 100644 (file)
@@ -218,6 +218,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
        if (error)
                goto out_drop_write;
 
+       error = -EACCES;
+       if (!is_owner_or_cap(inode))
+               goto out;
+
+       error = 0;
        flags = ip->i_diskflags;
        new_flags = (flags & ~mask) | (reqflags & mask);
        if ((new_flags ^ flags) == 0)
@@ -275,8 +280,10 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
 {
        struct inode *inode = filp->f_path.dentry->d_inode;
        u32 fsflags, gfsflags;
+
        if (get_user(fsflags, ptr))
                return -EFAULT;
+
        gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags);
        if (!S_ISDIR(inode->i_mode)) {
                if (gfsflags & GFS2_DIF_INHERIT_JDATA)
index 51d8061fa07ac79667148b6fec357feff8b6088f..b5612cbb62a51b75dc97699490658ce6939a4118 100644 (file)
@@ -242,34 +242,38 @@ fail:
 }
 
 /**
- * gfs2_unlinked_inode_lookup - Lookup an unlinked inode for reclamation
+ * gfs2_process_unlinked_inode - Lookup an unlinked inode for reclamation
+ *                               and try to reclaim it by doing iput.
+ *
+ * This function assumes no rgrp locks are currently held.
+ *
  * @sb: The super block
  * no_addr: The inode number
- * @@inode: A pointer to the inode found, if any
  *
- * Returns: 0 and *inode if no errors occurred.  If an error occurs,
- *          the resulting *inode may or may not be NULL.
  */
 
-int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
-                              struct inode **inode)
+void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr)
 {
        struct gfs2_sbd *sdp;
        struct gfs2_inode *ip;
        struct gfs2_glock *io_gl;
        int error;
        struct gfs2_holder gh;
+       struct inode *inode;
 
-       *inode = gfs2_iget_skip(sb, no_addr);
+       inode = gfs2_iget_skip(sb, no_addr);
 
-       if (!(*inode))
-               return -ENOBUFS;
+       if (!inode)
+               return;
 
-       if (!((*inode)->i_state & I_NEW))
-               return -ENOBUFS;
+       /* If it's not a new inode, someone's using it, so leave it alone. */
+       if (!(inode->i_state & I_NEW)) {
+               iput(inode);
+               return;
+       }
 
-       ip = GFS2_I(*inode);
-       sdp = GFS2_SB(*inode);
+       ip = GFS2_I(inode);
+       sdp = GFS2_SB(inode);
        ip->i_no_formal_ino = -1;
 
        error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
@@ -284,15 +288,13 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
        set_bit(GIF_INVALID, &ip->i_flags);
        error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, LM_FLAG_TRY | GL_EXACT,
                                   &ip->i_iopen_gh);
-       if (unlikely(error)) {
-               if (error == GLR_TRYFAILED)
-                       error = 0;
+       if (unlikely(error))
                goto fail_iopen;
-       }
+
        ip->i_iopen_gh.gh_gl->gl_object = ip;
        gfs2_glock_put(io_gl);
 
-       (*inode)->i_mode = DT2IF(DT_UNKNOWN);
+       inode->i_mode = DT2IF(DT_UNKNOWN);
 
        /*
         * We must read the inode in order to work out its type in
@@ -303,16 +305,17 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
         */
        error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY,
                                   &gh);
-       if (unlikely(error)) {
-               if (error == GLR_TRYFAILED)
-                       error = 0;
+       if (unlikely(error))
                goto fail_glock;
-       }
+
        /* Inode is now uptodate */
        gfs2_glock_dq_uninit(&gh);
-       gfs2_set_iop(*inode);
+       gfs2_set_iop(inode);
+
+       /* The iput will cause it to be deleted. */
+       iput(inode);
+       return;
 
-       return 0;
 fail_glock:
        gfs2_glock_dq(&ip->i_iopen_gh);
 fail_iopen:
@@ -321,7 +324,8 @@ fail_put:
        ip->i_gl->gl_object = NULL;
        gfs2_glock_put(ip->i_gl);
 fail:
-       return error;
+       iget_failed(inode);
+       return;
 }
 
 static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
index e161461d4c5798bc8e2b2cccd4dcc8cb3446912a..300ada3f21de0cf5fc22677283343a76caf8200e 100644 (file)
@@ -84,8 +84,7 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip,
 extern void gfs2_set_iop(struct inode *inode);
 extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
                                       u64 no_addr, u64 no_formal_ino);
-extern int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
-                                     struct inode **inode);
+extern void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr);
 extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
 
 extern int gfs2_inode_refresh(struct gfs2_inode *ip);
index b593f0e28f259aee410dad764e77ba71056c06e0..6a857e24f9477f7fe8fbdb710220d8d05964a95e 100644 (file)
@@ -696,7 +696,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
  *
  */
 
-void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
+void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
 {
        struct gfs2_ail *ai;
 
index eb570b4ad443ca54fc2e3cac93876d01e09d484c..0d007f92023411b00015a74d247095e8f7354f37 100644 (file)
@@ -47,28 +47,21 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
        sdp->sd_log_head = sdp->sd_log_tail = value;
 }
 
-unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
+extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
                            unsigned int ssize);
 
-int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
-void gfs2_log_incr_head(struct gfs2_sbd *sdp);
+extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
+extern void gfs2_log_incr_head(struct gfs2_sbd *sdp);
 
-struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp);
-struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
+extern struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp);
+extern struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
                                      struct buffer_head *real);
-void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
+extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
+extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
+extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
 
-static inline void gfs2_log_flush(struct gfs2_sbd *sbd, struct gfs2_glock *gl)
-{
-       if (!gl || test_bit(GLF_LFLUSH, &gl->gl_flags))
-               __gfs2_log_flush(sbd, gl);
-}
-
-void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
-void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
-
-void gfs2_log_shutdown(struct gfs2_sbd *sdp);
-void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
-int gfs2_logd(void *data);
+extern void gfs2_log_shutdown(struct gfs2_sbd *sdp);
+extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
+extern int gfs2_logd(void *data);
 
 #endif /* __LOG_DOT_H__ */
index 117fa4171f62958b966a6c781240d293d5491823..171a744f8e45d172f4e43eb793ae4e08dba8ba23 100644 (file)
@@ -1192,7 +1192,6 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_alloc *al = ip->i_alloc;
-       struct inode *inode;
        int error = 0;
        u64 last_unlinked = NO_BLOCK, unlinked;
 
@@ -1210,22 +1209,27 @@ try_again:
        if (error)
                return error;
 
+       /* Find an rgrp suitable for allocation.  If it encounters any unlinked
+          dinodes along the way, error will equal -EAGAIN and unlinked will
+          contains it block address. We then need to look up that inode and
+          try to free it, and try the allocation again. */
        error = get_local_rgrp(ip, &unlinked, &last_unlinked);
        if (error) {
                if (ip != GFS2_I(sdp->sd_rindex))
                        gfs2_glock_dq_uninit(&al->al_ri_gh);
                if (error != -EAGAIN)
                        return error;
-               error = gfs2_unlinked_inode_lookup(ip->i_inode.i_sb,
-                                                  unlinked, &inode);
-               if (inode)
-                       iput(inode);
+
+               gfs2_process_unlinked_inode(ip->i_inode.i_sb, unlinked);
+               /* regardless of whether or not gfs2_process_unlinked_inode
+                  was successful, we don't want to repeat it again. */
+               last_unlinked = unlinked;
                gfs2_log_flush(sdp, NULL);
-               if (error == GLR_TRYFAILED)
-                       error = 0;
+               error = 0;
+
                goto try_again;
        }
-
+       /* no error, so we have the rgrp set in the inode's allocation. */
        al->al_file = file;
        al->al_line = line;