diff -urN lvm-ref/drivers/md/lvm.c lvm/drivers/md/lvm.c --- lvm-ref/drivers/md/lvm.c Thu Jul 12 07:59:14 2001 +++ lvm/drivers/md/lvm.c Thu Jul 12 08:11:38 2001 @@ -368,7 +368,7 @@ static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED; static struct buffer_head *_pe_requests; -static struct semaphore _pe_lock; +static DECLARE_RWSEM(_pe_lock); struct file_operations lvm_chr_fops = { @@ -454,7 +454,6 @@ /* initialise the pe lock */ pe_lock_req.lock = UNLOCK_PE; - init_MUTEX(&_pe_lock); /* optional read root VGDA */ /* @@ -1131,7 +1130,7 @@ lv_t *lv = vg_this->lv[LV_BLK(minor)]; - down(&lv->lv_snapshot_sem); + down_read(&lv->lv_snapshot_sem); if (!(lv->lv_status & LV_ACTIVE)) { printk(KERN_ALERT "%s - lvm_map: ll_rw_blk for inactive LV %s\n", @@ -1198,7 +1197,7 @@ } /* handle physical extents on the move */ - down(&_pe_lock); + down_read(&_pe_lock); if((pe_lock_req.lock == LOCK_PE) && (rdev_map == pe_lock_req.data.pv_dev) && (rsector_map >= pe_lock_req.data.pv_offset) && @@ -1209,17 +1208,17 @@ printk(KERN_ERR "%s -- bh uses low 2 bits of pointer\n", lvm_name); - up(&_pe_lock); + up_read(&_pe_lock); goto bad; } bh->b_reqnext = _pe_requests; _pe_requests = (struct buffer_head *) ((int) bh | rw); - up(&_pe_lock); - up(&lv->lv_snapshot_sem); + up_read(&_pe_lock); + up_read(&lv->lv_snapshot_sem); return 0; } - up(&_pe_lock); + up_read(&_pe_lock); /* statistic */ if (rw == WRITE || rw == WRITEA) @@ -1252,22 +1251,22 @@ /* Serializes the COW with the accesses to the snapshot device */ - down(&snap->lv_snapshot_sem); + down_write(&snap->lv_snapshot_sem); __remap_snapshot(rdev_map, rsector_map, pe_start, snap, vg_this); - up(&snap->lv_snapshot_sem); + up_write(&snap->lv_snapshot_sem); } } out: bh->b_rdev = rdev_map; bh->b_rsector = rsector_map; - up(&lv->lv_snapshot_sem); + up_read(&lv->lv_snapshot_sem); return 1; bad: buffer_IO_error(bh); - up(&lv->lv_snapshot_sem); + up_read(&lv->lv_snapshot_sem); return -1; } /* lvm_map() */ @@ -1366,26 +1365,26 @@ pe_lock_req = new_lock; - down(&_pe_lock); + down_write(&_pe_lock); pe_lock_req.lock = UNLOCK_PE; - up(&_pe_lock); + up_write(&_pe_lock); fsync_dev(pe_lock_req.data.lv_dev); - down(&_pe_lock); + down_write(&_pe_lock); pe_lock_req.lock = LOCK_PE; - up(&_pe_lock); + up_write(&_pe_lock); break; case UNLOCK_PE: - down(&_pe_lock); + down_write(&_pe_lock); pe_lock_req.lock = UNLOCK_PE; pe_lock_req.data.lv_dev = \ pe_lock_req.data.pv_dev = \ pe_lock_req.data.pv_offset = 0; q = (uint) _pe_requests; _pe_requests = 0; - up(&_pe_lock); + up_write(&_pe_lock); /* handle all deferred io for this PE */ while(q) { @@ -1865,7 +1864,7 @@ lv_ptr->lv_snapshot_hash_table = NULL; lv_ptr->lv_snapshot_hash_table_size = 0; lv_ptr->lv_snapshot_hash_mask = 0; - init_MUTEX(&lv_ptr->lv_snapshot_sem); + init_rwsem(&lv_ptr->lv_snapshot_sem); lv_ptr->lv_snapshot_use_rate = 0; vg_ptr->lv[l] = lv_ptr; @@ -2007,7 +2006,7 @@ fsync_dev_lockfs(org->lv_dev); #endif - down(&org->lv_snapshot_sem); + down_write(&org->lv_snapshot_sem); org->lv_access |= LV_SNAPSHOT_ORG; lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */ @@ -2016,7 +2015,7 @@ for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next); lv_ptr->lv_snapshot_prev = last; last->lv_snapshot_next = lv_ptr; - up(&org->lv_snapshot_sem); + up_write(&org->lv_snapshot_sem); } /* activate the logical volume */ @@ -2085,7 +2084,7 @@ * to the original lv before playing with it. */ lv_t * org = lv_ptr->lv_snapshot_org; - down(&org->lv_snapshot_sem); + down_write(&org->lv_snapshot_sem); /* remove this snapshot logical volume from the chain */ lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next; @@ -2098,7 +2097,7 @@ if (!org->lv_snapshot_next) { org->lv_access &= ~LV_SNAPSHOT_ORG; } - up(&org->lv_snapshot_sem); + up_write(&org->lv_snapshot_sem); lvm_snapshot_release(lv_ptr); @@ -2295,7 +2294,7 @@ return r; /* copy relevent fields */ - down(&old_lv->lv_snapshot_sem); + down_write(&old_lv->lv_snapshot_sem); if(new_lv->lv_access & LV_SNAPSHOT) { @@ -2337,7 +2336,7 @@ lv_t *snap; for(snap = old_lv->lv_snapshot_next; snap; snap = snap->lv_snapshot_next) { - down(&snap->lv_snapshot_sem); + down_write(&snap->lv_snapshot_sem); snap->lv_current_pe = old_lv->lv_current_pe; snap->lv_allocated_le = old_lv->lv_allocated_le; @@ -2349,13 +2348,13 @@ lvm_size[MINOR(snap->lv_dev)] = old_lv->lv_size >> 1; __update_hardblocksize(snap); - up(&snap->lv_snapshot_sem); + up_write(&snap->lv_snapshot_sem); } } } __update_hardblocksize(old_lv); - up(&old_lv->lv_snapshot_sem); + up_write(&old_lv->lv_snapshot_sem); return 0; } /* lvm_do_lv_extend_reduce() */ diff -urN lvm-ref/include/linux/lvm.h lvm/include/linux/lvm.h --- lvm-ref/include/linux/lvm.h Thu Jul 12 07:59:14 2001 +++ lvm/include/linux/lvm.h Thu Jul 12 08:01:17 2001 @@ -651,7 +651,7 @@ #ifdef __KERNEL__ struct kiobuf *lv_iobuf; struct kiobuf *lv_COW_table_iobuf; - struct semaphore lv_snapshot_sem; + struct rw_semaphore lv_snapshot_sem; struct list_head *lv_snapshot_hash_table; uint32_t lv_snapshot_hash_table_size; uint32_t lv_snapshot_hash_mask;