]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 14 Aug 2007 17:00:29 +0000 (10:00 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 14 Aug 2007 17:00:29 +0000 (10:00 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes:
  [GFS2] Revert remounting w/o acl option leaves acls enabled
  [GFS2] Fix setting of inherit jdata attr
  [GFS2] Fix incorrect error path in prepare_write()
  [GFS2] Fix incorrect return code in rgrp.c
  [GFS2] soft lockup in rgblk_search
  [GFS2] soft lockup detected in databuf_lo_before_commit
  [DLM] fix basts for granted PR waiting CW
  [DLM] More othercon fixes
  [DLM] Fix memory leak in dlm_add_member() when dlm_node_weight() returns less than zero
  [DLM] zero unused parts of sockaddr_storage
  [DLM] fix NULL ls usage
  [DLM] Clear othercon pointers when a connection is closed

fs/dlm/lock.c
fs/dlm/lowcomms.c
fs/dlm/member.c
fs/dlm/rcom.c
fs/gfs2/lops.c
fs/gfs2/mount.c
fs/gfs2/ops_address.c
fs/gfs2/ops_file.c
fs/gfs2/rgrp.c

index b455919c19984ad408d4ca498ad72f40a7d33d1f..2082daf083d86cdec3b3697e061f8f3ff703e867 100644 (file)
@@ -1670,9 +1670,10 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
    with a deadlk here, we'd have to generate something like grant_lock with
    the deadlk error.) */
 
-/* returns the highest requested mode of all blocked conversions */
+/* Returns the highest requested mode of all blocked conversions; sets
+   cw if there's a blocked conversion to DLM_LOCK_CW. */
 
-static int grant_pending_convert(struct dlm_rsb *r, int high)
+static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw)
 {
        struct dlm_lkb *lkb, *s;
        int hi, demoted, quit, grant_restart, demote_restart;
@@ -1709,6 +1710,9 @@ static int grant_pending_convert(struct dlm_rsb *r, int high)
                }
 
                hi = max_t(int, lkb->lkb_rqmode, hi);
+
+               if (cw && lkb->lkb_rqmode == DLM_LOCK_CW)
+                       *cw = 1;
        }
 
        if (grant_restart)
@@ -1721,29 +1725,52 @@ static int grant_pending_convert(struct dlm_rsb *r, int high)
        return max_t(int, high, hi);
 }
 
-static int grant_pending_wait(struct dlm_rsb *r, int high)
+static int grant_pending_wait(struct dlm_rsb *r, int high, int *cw)
 {
        struct dlm_lkb *lkb, *s;
 
        list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
                if (can_be_granted(r, lkb, 0, NULL))
                        grant_lock_pending(r, lkb);
-                else
+                else {
                        high = max_t(int, lkb->lkb_rqmode, high);
+                       if (lkb->lkb_rqmode == DLM_LOCK_CW)
+                               *cw = 1;
+               }
        }
 
        return high;
 }
 
+/* cw of 1 means there's a lock with a rqmode of DLM_LOCK_CW that's blocked
+   on either the convert or waiting queue.
+   high is the largest rqmode of all locks blocked on the convert or
+   waiting queue. */
+
+static int lock_requires_bast(struct dlm_lkb *gr, int high, int cw)
+{
+       if (gr->lkb_grmode == DLM_LOCK_PR && cw) {
+               if (gr->lkb_highbast < DLM_LOCK_EX)
+                       return 1;
+               return 0;
+       }
+
+       if (gr->lkb_highbast < high &&
+           !__dlm_compat_matrix[gr->lkb_grmode+1][high+1])
+               return 1;
+       return 0;
+}
+
 static void grant_pending_locks(struct dlm_rsb *r)
 {
        struct dlm_lkb *lkb, *s;
        int high = DLM_LOCK_IV;
+       int cw = 0;
 
        DLM_ASSERT(is_master(r), dlm_dump_rsb(r););
 
-       high = grant_pending_convert(r, high);
-       high = grant_pending_wait(r, high);
+       high = grant_pending_convert(r, high, &cw);
+       high = grant_pending_wait(r, high, &cw);
 
        if (high == DLM_LOCK_IV)
                return;
@@ -1751,27 +1778,41 @@ static void grant_pending_locks(struct dlm_rsb *r)
        /*
         * If there are locks left on the wait/convert queue then send blocking
         * ASTs to granted locks based on the largest requested mode (high)
-        * found above. FIXME: highbast < high comparison not valid for PR/CW.
+        * found above.
         */
 
        list_for_each_entry_safe(lkb, s, &r->res_grantqueue, lkb_statequeue) {
-               if (lkb->lkb_bastaddr && (lkb->lkb_highbast < high) &&
-                   !__dlm_compat_matrix[lkb->lkb_grmode+1][high+1]) {
-                       queue_bast(r, lkb, high);
+               if (lkb->lkb_bastaddr && lock_requires_bast(lkb, high, cw)) {
+                       if (cw && high == DLM_LOCK_PR)
+                               queue_bast(r, lkb, DLM_LOCK_CW);
+                       else
+                               queue_bast(r, lkb, high);
                        lkb->lkb_highbast = high;
                }
        }
 }
 
+static int modes_require_bast(struct dlm_lkb *gr, struct dlm_lkb *rq)
+{
+       if ((gr->lkb_grmode == DLM_LOCK_PR && rq->lkb_rqmode == DLM_LOCK_CW) ||
+           (gr->lkb_grmode == DLM_LOCK_CW && rq->lkb_rqmode == DLM_LOCK_PR)) {
+               if (gr->lkb_highbast < DLM_LOCK_EX)
+                       return 1;
+               return 0;
+       }
+
+       if (gr->lkb_highbast < rq->lkb_rqmode && !modes_compat(gr, rq))
+               return 1;
+       return 0;
+}
+
 static void send_bast_queue(struct dlm_rsb *r, struct list_head *head,
                            struct dlm_lkb *lkb)
 {
        struct dlm_lkb *gr;
 
        list_for_each_entry(gr, head, lkb_statequeue) {
-               if (gr->lkb_bastaddr &&
-                   gr->lkb_highbast < lkb->lkb_rqmode &&
-                   !modes_compat(gr, lkb)) {
+               if (gr->lkb_bastaddr && modes_require_bast(gr, lkb)) {
                        queue_bast(r, gr, lkb->lkb_rqmode);
                        gr->lkb_highbast = lkb->lkb_rqmode;
                }
@@ -2235,7 +2276,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
           before we try again to grant this one. */
 
        if (is_demoted(lkb)) {
-               grant_pending_convert(r, DLM_LOCK_IV);
+               grant_pending_convert(r, DLM_LOCK_IV, NULL);
                if (_can_be_granted(r, lkb, 1)) {
                        grant_lock(r, lkb);
                        queue_cast(r, lkb, 0);
index dd362739d291e8a5d125ec2d2172e19d497bdecc..9e9d2e82f40fb36a62307e92b5ab48285a3c4654 100644 (file)
@@ -313,6 +313,7 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
                in6_addr->sin6_port = cpu_to_be16(port);
                *addr_len = sizeof(struct sockaddr_in6);
        }
+       memset((char *)saddr + *addr_len, 0, sizeof(struct sockaddr_storage) - *addr_len);
 }
 
 /* Close a remote connection and tidy up */
@@ -332,8 +333,19 @@ static void close_connection(struct connection *con, bool and_other)
                __free_page(con->rx_page);
                con->rx_page = NULL;
        }
-       con->retries = 0;
-       mutex_unlock(&con->sock_mutex);
+
+       /* If we are an 'othercon' then NULL the pointer to us
+          from the parent and tidy ourself up */
+       if (test_bit(CF_IS_OTHERCON, &con->flags)) {
+               struct connection *parent = __nodeid2con(con->nodeid, 0);
+               parent->othercon = NULL;
+               kmem_cache_free(con_cache, con);
+       }
+       else {
+               /* Parent connections get reused */
+               con->retries = 0;
+               mutex_unlock(&con->sock_mutex);
+       }
 }
 
 /* We only send shutdown messages to nodes that are not part of the cluster */
@@ -631,7 +643,7 @@ out_resched:
 
 out_close:
        mutex_unlock(&con->sock_mutex);
-       if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
+       if (ret != -EAGAIN) {
                close_connection(con, false);
                /* Reconnect when there is something to send */
        }
@@ -1122,8 +1134,6 @@ static int tcp_listen_for_all(void)
 
        log_print("Using TCP for communications");
 
-       set_bit(CF_IS_OTHERCON, &con->flags);
-
        sock = tcp_create_listen_sock(con, dlm_local_addr[0]);
        if (sock) {
                add_sock(sock, con);
@@ -1407,7 +1417,7 @@ void dlm_lowcomms_stop(void)
        for (i = 0; i <= max_nodeid; i++) {
                con = __nodeid2con(i, 0);
                if (con) {
-                       con->flags |= 0xFF;
+                       con->flags |= 0x0F;
                        if (con->sock)
                                con->sock->sk->sk_user_data = NULL;
                }
@@ -1423,8 +1433,6 @@ void dlm_lowcomms_stop(void)
                con = __nodeid2con(i, 0);
                if (con) {
                        close_connection(con, true);
-                       if (con->othercon)
-                               kmem_cache_free(con_cache, con->othercon);
                        kmem_cache_free(con_cache, con);
                }
        }
index 073599dced2ab4b2562f8f7df44db66aeaa079cc..d09977528f692c7e133a9d7702cae88411536e75 100644 (file)
@@ -56,8 +56,10 @@ static int dlm_add_member(struct dlm_ls *ls, int nodeid)
                return -ENOMEM;
 
        w = dlm_node_weight(ls->ls_name, nodeid);
-       if (w < 0)
+       if (w < 0) {
+               kfree(memb);
                return w;
+       }
 
        memb->nodeid = nodeid;
        memb->weight = w;
index e3a1527cbdbe7c8cd4bb0a8b6605e486b8ea538c..188b91c027e4b16a811c30b398654018ad63a771 100644 (file)
@@ -386,8 +386,7 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
        dlm_recover_process_copy(ls, rc_in);
 }
 
-static int send_ls_not_ready(struct dlm_ls *ls, int nodeid,
-                            struct dlm_rcom *rc_in)
+static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
 {
        struct dlm_rcom *rc;
        struct rcom_config *rf;
@@ -395,7 +394,7 @@ static int send_ls_not_ready(struct dlm_ls *ls, int nodeid,
        char *mb;
        int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
 
-       mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb);
+       mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_NOFS, &mb);
        if (!mh)
                return -ENOBUFS;
        memset(mb, 0, mb_len);
@@ -465,7 +464,7 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid)
                log_print("lockspace %x from %d type %x not found",
                          hd->h_lockspace, nodeid, rc->rc_type);
                if (rc->rc_type == DLM_RCOM_STATUS)
-                       send_ls_not_ready(ls, nodeid, rc);
+                       send_ls_not_ready(nodeid, rc);
                return;
        }
 
index aff70f0698fdd887799e3d23a0057ea715714112..3b395c41b2f3f9acefc623e6e008949231b1e8d3 100644 (file)
@@ -486,8 +486,8 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
                gfs2_pin(sdp, bd->bd_bh);
                tr->tr_num_databuf_new++;
        }
-       sdp->sd_log_num_databuf++;
        gfs2_log_lock(sdp);
+       sdp->sd_log_num_databuf++;
        list_add(&le->le_list, &sdp->sd_log_le_databuf);
        gfs2_log_unlock(sdp);
 }
@@ -523,7 +523,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
        struct buffer_head *bh = NULL,*bh1 = NULL;
        struct gfs2_log_descriptor *ld;
        unsigned int limit;
-       unsigned int total_dbuf = sdp->sd_log_num_databuf;
+       unsigned int total_dbuf;
        unsigned int total_jdata = sdp->sd_log_num_jdata;
        unsigned int num, n;
        __be64 *ptr = NULL;
@@ -535,6 +535,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
         * into the log along with a header
         */
        gfs2_log_lock(sdp);
+       total_dbuf = sdp->sd_log_num_databuf;
        bd2 = bd1 = list_prepare_entry(bd1, &sdp->sd_log_le_databuf,
                                       bd_le.le_list);
        while(total_dbuf) {
@@ -653,6 +654,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
                                break;
                }
                bh = NULL;
+               BUG_ON(total_dbuf < num);
                total_dbuf -= num;
                total_jdata -= num;
        }
index 6f006a804db33c48310c5af608ed4aa53805625c..4864659555d4f94d49132a2727a4acd0b5e1d5e4 100644 (file)
@@ -82,19 +82,20 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
        char *options, *o, *v;
        int error = 0;
 
-       /*  If someone preloaded options, use those instead  */
-       spin_lock(&gfs2_sys_margs_lock);
-       if (!remount && gfs2_sys_margs) {
-               data = gfs2_sys_margs;
-               gfs2_sys_margs = NULL;
-       }
-       spin_unlock(&gfs2_sys_margs_lock);
+       if (!remount) {
+               /*  If someone preloaded options, use those instead  */
+               spin_lock(&gfs2_sys_margs_lock);
+               if (gfs2_sys_margs) {
+                       data = gfs2_sys_margs;
+                       gfs2_sys_margs = NULL;
+               }
+               spin_unlock(&gfs2_sys_margs_lock);
 
-       /*  Set some defaults  */
-       memset(args, 0, sizeof(struct gfs2_args));
-       args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
-       args->ar_quota = GFS2_QUOTA_DEFAULT;
-       args->ar_data = GFS2_DATA_DEFAULT;
+               /*  Set some defaults  */
+               args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
+               args->ar_quota = GFS2_QUOTA_DEFAULT;
+               args->ar_data = GFS2_DATA_DEFAULT;
+       }
 
        /* Split the options into tokens with the "," character and
           process them */
index ce90032c010ec7176d8f31505a5c859833dc3650..42a5f58f6fca4adf5ad1faae9edec36939b05d2c 100644 (file)
@@ -416,7 +416,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page,
 
        error = gfs2_trans_begin(sdp, rblocks, 0);
        if (error)
-               goto out;
+               goto out_trans_fail;
 
        if (gfs2_is_stuffed(ip)) {
                if (end > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
@@ -434,6 +434,7 @@ prepare_write:
 out:
        if (error) {
                gfs2_trans_end(sdp);
+out_trans_fail:
                if (alloc_required) {
                        gfs2_inplace_release(ip);
 out_qunlock:
index 77342113011657ee4e9c3697d072816d6ebc77d6..94d76ace0b95b840427552c33636f3c0bab46fd3 100644 (file)
@@ -177,8 +177,8 @@ static const u32 fsflags_to_gfs2[32] = {
        [5] = GFS2_DIF_APPENDONLY,
        [7] = GFS2_DIF_NOATIME,
        [12] = GFS2_DIF_EXHASH,
-       [14] = GFS2_DIF_JDATA,
-       [20] = GFS2_DIF_DIRECTIO,
+       [14] = GFS2_DIF_INHERIT_JDATA,
+       [20] = GFS2_DIF_INHERIT_DIRECTIO,
 };
 
 static const u32 gfs2_to_fsflags[32] = {
@@ -187,8 +187,6 @@ static const u32 gfs2_to_fsflags[32] = {
        [gfs2fl_AppendOnly] = FS_APPEND_FL,
        [gfs2fl_NoAtime] = FS_NOATIME_FL,
        [gfs2fl_ExHash] = FS_INDEX_FL,
-       [gfs2fl_Jdata] = FS_JOURNAL_DATA_FL,
-       [gfs2fl_Directio] = FS_DIRECTIO_FL,
        [gfs2fl_InheritDirectio] = FS_DIRECTIO_FL,
        [gfs2fl_InheritJdata] = FS_JOURNAL_DATA_FL,
 };
@@ -207,6 +205,12 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
                return error;
 
        fsflags = fsflags_cvt(gfs2_to_fsflags, ip->i_di.di_flags);
+       if (!S_ISDIR(inode->i_mode)) {
+               if (ip->i_di.di_flags & GFS2_DIF_JDATA)
+                       fsflags |= FS_JOURNAL_DATA_FL;
+               if (ip->i_di.di_flags & GFS2_DIF_DIRECTIO)
+                       fsflags |= FS_DIRECTIO_FL;
+       }
        if (put_user(fsflags, ptr))
                error = -EFAULT;
 
@@ -270,13 +274,6 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
        if ((new_flags ^ flags) == 0)
                goto out;
 
-       if (S_ISDIR(inode->i_mode)) {
-               if ((new_flags ^ flags) & GFS2_DIF_JDATA)
-                       new_flags ^= (GFS2_DIF_JDATA|GFS2_DIF_INHERIT_JDATA);
-               if ((new_flags ^ flags) & GFS2_DIF_DIRECTIO)
-                       new_flags ^= (GFS2_DIF_DIRECTIO|GFS2_DIF_INHERIT_DIRECTIO);
-       }
-
        error = -EINVAL;
        if ((new_flags ^ flags) & ~GFS2_FLAGS_USER_SET)
                goto out;
@@ -315,11 +312,19 @@ out:
 
 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);
-       return do_gfs2_set_flags(filp, gfsflags, ~0);
+       if (!S_ISDIR(inode->i_mode)) {
+               if (gfsflags & GFS2_DIF_INHERIT_JDATA)
+                       gfsflags ^= (GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA);
+               if (gfsflags & GFS2_DIF_INHERIT_DIRECTIO)
+                       gfsflags ^= (GFS2_DIF_DIRECTIO | GFS2_DIF_INHERIT_DIRECTIO);
+               return do_gfs2_set_flags(filp, gfsflags, ~0);
+       }
+       return do_gfs2_set_flags(filp, gfsflags, ~GFS2_DIF_JDATA);
 }
 
 static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
index e4e040625153aa29b2254e51276eb6ac9807380e..ce48c4594ec88f9dc9fb64eb8d0413c5a04cc272 100644 (file)
@@ -863,16 +863,19 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
        u64 no_addr;
 
        for(;;) {
+               if (goal >= rgd->rd_data)
+                       break;
                goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
                                    GFS2_BLKST_UNLINKED);
-               if (goal == 0)
-                       return 0;
+               if (goal == BFITNOENT)
+                       break;
                no_addr = goal + rgd->rd_data0;
-               if (no_addr <= *last_unlinked)
+               goal++;
+               if (no_addr < *last_unlinked)
                        continue;
                *last_unlinked = no_addr;
                inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
-                                       no_addr, -1);
+                                         no_addr, -1);
                if (!IS_ERR(inode))
                        return inode;
        }
@@ -1313,7 +1316,7 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
                                    bi->bi_len, blk, new_state);
        }
 
-       return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk;
+       return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk;
 }
 
 /**
@@ -1393,6 +1396,7 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip)
                goal = rgd->rd_last_alloc_data;
 
        blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
+       BUG_ON(blk == BFITNOENT);
        rgd->rd_last_alloc_data = blk;
 
        block = rgd->rd_data0 + blk;
@@ -1437,6 +1441,7 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip)
                goal = rgd->rd_last_alloc_meta;
 
        blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
+       BUG_ON(blk == BFITNOENT);
        rgd->rd_last_alloc_meta = blk;
 
        block = rgd->rd_data0 + blk;
@@ -1478,6 +1483,7 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
 
        blk = rgblk_search(rgd, rgd->rd_last_alloc_meta,
                           GFS2_BLKST_FREE, GFS2_BLKST_DINODE);
+       BUG_ON(blk == BFITNOENT);
 
        rgd->rd_last_alloc_meta = blk;