4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
26 * Copyright 2012 Milan Jurik. All rights reserved.
29 #include <sys/param.h>
30 #include <sys/systm.h>
32 #include <sys/debug.h>
40 #include <sys/cmn_err.h>
41 #include <sys/sysmacros.h>
42 #include <sys/types.h>
43 #include <sys/mkdev.h>
46 #include <sys/modctl.h>
48 #include <sys/sunddi.h>
52 #include <sys/lvm/mdvar.h>
53 #include <sys/lvm/md_trans.h>
54 #include <sys/lvm/md_notify.h>
55 #include <sys/lvm/md_convert.h>
57 #include <sys/sysevent/eventdefs.h>
58 #include <sys/sysevent/svm.h>
60 md_ops_t trans_md_ops
;
62 md_ops_t
*md_interface_ops
= &trans_md_ops
;
65 extern unit_t md_nunits
;
66 extern set_t md_nsets
;
67 extern md_set_t md_set
[];
69 extern major_t md_major
;
71 extern int md_trans_ioctl(dev_t
, int, void *, int, IOLOCK
*);
72 extern md_krwlock_t md_unit_array_rw
;
74 extern mdq_anchor_t md_done_daemon
;
76 extern int md_in_upgrade
;
78 static kmem_cache_t
*trans_parent_cache
= NULL
;
79 kmem_cache_t
*trans_child_cache
= NULL
;
83 * ROUTINES FOR TESTING:
88 extern int _init_ioctl();
90 return (_init_ioctl());
95 extern int _fini_ioctl();
105 * BEGIN RELEASE DEBUG
106 * The following routines remain in the released product for testability
109 trans_done_shadow(buf_t
*bp
)
112 md_tps_t
*ps
= (md_tps_t
*)bp
->b_chain
;
116 mutex_enter(&ps
->ps_mx
);
118 if (ps
->ps_count
> 0) {
119 if ((bp
->b_flags
& B_ERROR
) != 0) {
120 pb
->b_flags
|= B_ERROR
;
121 pb
->b_error
= bp
->b_error
;
123 mutex_exit(&ps
->ps_mx
);
124 kmem_cache_free(trans_child_cache
, bp
);
126 mutex_exit(&ps
->ps_mx
);
127 mutex_destroy(&ps
->ps_mx
);
134 shadow_debug(mt_unit_t
*un
, /* trans unit info */
135 buf_t
*pb
, /* primary buffer */
136 md_tps_t
*ps
, /* trans parent save */
137 buf_t
*cb
, /* buffer for writing to master */
141 buf_t
*sb
; /* Shadow buffer */
143 mutex_init(&ps
->ps_mx
, NULL
, MUTEX_DEFAULT
, NULL
);
144 ps
->ps_count
= 2; /* Write child buffer & shadow */
145 cb
->b_iodone
= trans_done_shadow
;
146 sb
= kmem_cache_alloc(trans_child_cache
, MD_ALLOCFLAGS
);
147 trans_child_init(sb
);
148 sb
= bioclone(pb
, 0, pb
->b_bcount
, md_dev64_to_dev(un
->un_s_dev
),
149 pb
->b_blkno
, trans_done_shadow
, sb
, KM_NOSLEEP
);
151 sb
->b_flags
|= B_ASYNC
;
152 sb
->b_chain
= (void *)ps
;
153 md_call_strategy(sb
, flag
| MD_STR_MAPPED
, private);
160 * COMMON MEMORY ALLOCATION ROUTINES (so that we can discover leaks)
163 md_trans_zalloc(size_t nb
)
165 TRANSSTATS(ts_trans_zalloc
);
166 TRANSSTATSADD(ts_trans_alloced
, nb
);
167 return (kmem_zalloc(nb
, KM_SLEEP
));
170 md_trans_alloc(size_t nb
)
172 TRANSSTATS(ts_trans_alloc
);
173 TRANSSTATSADD(ts_trans_alloced
, nb
);
174 return (kmem_alloc(nb
, KM_SLEEP
));
177 md_trans_free(void *va
, size_t nb
)
179 TRANSSTATS(ts_trans_free
);
180 TRANSSTATSADD(ts_trans_freed
, nb
);
186 trans_parent_init(md_tps_t
*ps
)
188 bzero(ps
, sizeof (md_tps_t
));
193 trans_child_constructor(void *p
, void *d1
, int d2
)
200 trans_child_init(struct buf
*bp
)
207 trans_child_destructor(void *p
, void *d
)
213 trans_commit(mt_unit_t
*un
, int domstr
)
215 mddb_recid_t recids
[4];
219 if (md_get_setstatus(MD_UN2SET(un
)) & MD_SET_STALE
)
222 recids
[ri
++] = un
->c
.un_record_id
;
225 if (md_getmajor(un
->un_m_dev
) == md_major
) {
226 su
= MD_UNIT(md_getminor(un
->un_m_dev
));
227 recids
[ri
++] = su
->c
.un_record_id
;
234 uniqtime32(&un
->un_timestamp
);
235 mddb_commitrecs_wrapper(recids
);
239 trans_close_all_devs(mt_unit_t
*un
)
241 if ((un
->un_flags
& TRANS_NEED_OPEN
) == 0) {
242 md_layered_close(un
->un_m_dev
, MD_OFLG_NULL
);
244 ldl_close_dev(un
->un_l_unit
);
245 un
->un_flags
|= TRANS_NEED_OPEN
;
250 trans_open_all_devs(mt_unit_t
*un
)
253 minor_t mnum
= MD_SID(un
);
254 md_dev64_t tmpdev
= un
->un_m_dev
;
255 set_t setno
= MD_MIN2SET(MD_SID(un
));
256 side_t side
= mddb_getsidenum(setno
);
259 * Do the open by device id if it is regular device
261 if ((md_getmajor(tmpdev
) != md_major
) &&
262 md_devid_found(setno
, side
, un
->un_m_key
) == 1) {
263 tmpdev
= md_resolve_bydevid(mnum
, tmpdev
, un
->un_m_key
);
265 err
= md_layered_open(mnum
, &tmpdev
, MD_OFLG_NULL
);
266 un
->un_m_dev
= tmpdev
;
272 err
= ldl_open_dev(un
, un
->un_l_unit
);
274 md_layered_close(tmpdev
, MD_OFLG_NULL
);
284 trans_build_incore(void *p
, int snarfing
)
286 mt_unit_t
*un
= (mt_unit_t
*)p
;
291 * initialize debug mode and always start with no shadowing.
294 un
->un_debug
= mt_debug
;
295 un
->un_s_dev
= NODEV64
;
299 if (MD_UNIT(mnum
) != NULL
)
302 setno
= MD_MIN2SET(mnum
);
305 * If snarfing the metatrans device,
306 * then remake the device number
309 un
->un_m_dev
= md_getdevnum(setno
, mddb_getsidenum(setno
),
310 un
->un_m_key
, MD_NOTRUST_DEVT
);
314 * db rec is partially deleted; finish the db delete later
316 if (MD_STATUS(un
) & MD_UN_BEING_RESET
) {
317 mddb_setrecprivate(un
->c
.un_record_id
, MD_PRV_PENDCLEAN
);
322 * With the current device id implementation there is possibility
323 * that we may have NODEV if the underlying can't be resolved at
324 * snarf time. If this is the case we want to be consistent with
325 * the normal behavior and continue to allow the snarf of unit
326 * and resolve the devt at the open time
328 if ((md_getmajor(un
->un_m_dev
) == md_major
) &&
329 (md_dev_exists(un
->un_m_dev
) == 0)) {
334 * retain the detach status; reset open status
336 un
->un_flags
&= (TRANS_DETACHING
| TRANS_DETACHED
);
337 un
->un_flags
|= TRANS_NEED_OPEN
;
338 if ((un
->un_flags
& TRANS_DETACHED
) == 0)
339 un
->un_flags
|= TRANS_ATTACHING
;
342 * log device not set up yet; try again later
344 if ((un
->un_flags
& TRANS_DETACHED
) == 0)
345 if (ldl_findlog(un
->un_l_recid
) == NULL
)
349 * initialize incore fields
352 un
->un_l_unit
= NULL
;
353 un
->un_deltamap
= NULL
;
355 un
->un_logmap
= NULL
;
356 un
->un_matamap
= NULL
;
357 un
->un_shadowmap
= NULL
;
360 un
->un_dev
= md_makedevice(md_major
, mnum
);
363 /* necessary because capability didn't exist pre-4.1 */
364 MD_CAPAB(un
) = (MD_CAN_META_CHILD
& ~MD_CAN_PARENT
);
372 * check for master dev dynconcat
374 if (md_getmajor(un
->un_m_dev
) == md_major
) {
377 c
= MD_UNIT(md_getminor(un
->un_m_dev
));
378 un
->c
.un_total_blocks
= c
->un_total_blocks
;
381 /* place various information in the in-core data structures */
382 md_nblocks_set(mnum
, un
->c
.un_total_blocks
);
389 trans_detach(mt_unit_t
*un
, int force
)
391 mdi_unit_t
*ui
= MDI_UNIT(MD_SID(un
));
395 * The caller is responsible for single-threading this routine.
402 * already detached or the log isn't attached yet; do nothing
404 if (un
->un_flags
& (TRANS_DETACHED
| TRANS_ATTACHING
))
408 * set state to detaching
410 if (force
|| !md_unit_isopen(ui
)) {
411 un
->un_flags
|= TRANS_DETACHING
;
415 SE_NOTIFY(EC_SVM_CONFIG
, ESC_SVM_DETACHING
, TAG_METADEVICE
,
416 MD_UN2SET(un
), MD_SID(un
));
422 if (md_unit_isopen(ui
))
428 * flags committed to TRANS_DETACHED in database
429 * un->un_l_unit set to NULL
432 error
= ldl_reset(un
, 1, force
);
442 SE_NOTIFY(EC_SVM_CONFIG
, ESC_SVM_DETACH
, TAG_METADEVICE
, MD_UN2SET(un
),
449 trans_attach(mt_unit_t
*un
, int attaching
)
451 mdi_unit_t
*ui
= MDI_UNIT(MD_SID(un
));
455 * called from snarf, set, and attach. Hence, the attaching param
456 * The caller is responsible for single-threading this routine.
460 * not attaching; do nothing
462 if ((un
->un_flags
& TRANS_ATTACHING
) == 0)
466 * find log unit struct
468 ul
= ldl_findlog(un
->un_l_recid
);
471 un
->un_l_dev
= ul
->un_dev
;
474 * device is busy; do nothing
476 if (attaching
&& md_unit_isopen(ui
))
479 * other functions use non-NULL un_l_unit as detach/attach flag
484 * add metatrans device to the log's list of mt devices
491 un
->un_flags
&= ~TRANS_ATTACHING
;
496 trans_reset(mt_unit_t
*un
, minor_t mnum
, int removing
, int force
)
499 mddb_recid_t vtoc_id
;
503 * reset log, maps, and ufs interface
505 error
= ldl_reset(un
, removing
, force
);
510 * done with underyling devices
512 trans_close_all_devs(un
);
514 md_destroy_unit_incore(mnum
, &trans_md_ops
);
516 md_nblocks_set(mnum
, -1ULL);
517 MD_UNIT(mnum
) = NULL
;
522 md_reset_parent(un
->un_m_dev
);
523 MD_STATUS(un
) |= MD_UN_BEING_RESET
;
525 SE_NOTIFY(EC_SVM_CONFIG
, ESC_SVM_DELETE
, TAG_METADEVICE
, MD_UN2SET(un
),
528 /* Save the mstr key */
529 sv
.setno
= MD_MIN2SET(mnum
);
530 sv
.key
= un
->un_m_key
;
532 vtoc_id
= un
->c
.un_vtoc_id
;
534 mddb_deleterec_wrapper(un
->c
.un_record_id
);
536 /* Remove the vtoc, if present */
538 mddb_deleterec_wrapper(vtoc_id
);
539 md_rem_names(&sv
, 1);
544 trans_wait_panic(struct buf
*cb
)
546 while ((cb
->b_flags
& B_DONE
) == 0) {
547 md_daemon(1, &md_done_daemon
);
553 trans_error(md_tps_t
*ps
)
565 * gather up params for cmn_err
567 if (pb
->b_flags
& B_READ
)
571 md_dev
= md_expldev(pb
->b_edev
);
572 m_dev
= ps
->ps_un
->un_m_dev
;
575 * free up the resources for this request and done the errored buf
577 md_kstat_done(ui
, pb
, 0);
578 kmem_cache_free(trans_parent_cache
, ps
);
579 md_unit_readerexit(ui
);
583 * print pretty error message
585 cmn_err(CE_WARN
, "md: %s: %s error on %s",
586 md_shortname(md_getminor(md_dev
)), str
,
587 md_devname(MD_DEV2SET(md_dev
), m_dev
, NULL
, 0));
591 trans_done(struct buf
*cb
)
597 ps
= (md_tps_t
*)cb
->b_chain
;
601 if (cb
->b_flags
& B_ERROR
) {
602 pb
->b_flags
|= B_ERROR
;
603 pb
->b_error
= cb
->b_error
;
605 * device not in hard error state; report error
607 if (!ldl_isherror(ps
->ps_un
->un_l_unit
)) {
608 daemon_request(&md_done_daemon
, trans_error
,
609 (daemon_queue_t
*)ps
, REQ_OLD
);
611 if (cb
->b_flags
& B_REMAPPED
)
614 cb
->b_flags
|= B_DONE
;
616 kmem_cache_free(trans_child_cache
, cb
);
622 if (cb
->b_flags
& B_REMAPPED
)
626 cb
->b_flags
|= B_DONE
;
628 kmem_cache_free(trans_child_cache
, cb
);
629 kmem_cache_free(trans_parent_cache
, ps
);
630 md_kstat_done(ui
, pb
, 0);
631 md_unit_readerexit(ui
);
638 md_trans_strategy(buf_t
*pb
, int flag
, void *private)
641 buf_t
*cb
; /* child buf pointer */
645 ui
= MDI_UNIT(getminor(pb
->b_edev
));
647 md_kstat_waitq_enter(ui
);
649 un
= (mt_unit_t
*)md_unit_readerlock(ui
);
651 if (md_inc_iocount(MD_MIN2SET(getminor(pb
->b_edev
))) != 0) {
652 pb
->b_flags
|= B_ERROR
;
654 pb
->b_resid
= pb
->b_bcount
;
655 md_kstat_waitq_exit(ui
);
656 md_unit_readerexit(ui
);
661 ASSERT(!(flag
& MD_STR_NOTTOP
));
664 if (md_checkbuf(ui
, (md_unit_t
*)un
, pb
) != 0) {
665 md_kstat_waitq_exit(ui
);
671 ps
= kmem_cache_alloc(trans_parent_cache
, MD_ALLOCFLAGS
);
672 trans_parent_init(ps
);
675 * Save essential information from the original buffhdr
676 * in the md_save structure.
682 cb
= kmem_cache_alloc(trans_child_cache
, MD_ALLOCFLAGS
);
683 trans_child_init(cb
);
685 cb
= bioclone(pb
, 0, pb
->b_bcount
, md_dev64_to_dev(un
->un_m_dev
),
686 pb
->b_blkno
, trans_done
, cb
, KM_NOSLEEP
);
688 cb
->b_chain
= (void *)ps
;
692 * The following calls shadow debug for testing purposes if we are
693 * writing and if shadowing is turned on.
695 if ((un
->un_s_dev
!= NODEV64
) &&
696 ((pb
->b_flags
& B_READ
) == 0))
697 shadow_debug(un
, pb
, ps
, cb
, flag
, private);
699 md_kstat_waitq_to_runq(ui
);
701 (void) md_call_strategy(cb
, flag
| MD_STR_MAPPED
| MD_NOBLOCK
, private);
704 * panic in progress; process daemon queues
707 trans_wait_panic(cb
);
708 kmem_cache_free(trans_child_cache
, cb
);
714 md_trans_read(dev_t dev
, struct uio
*uio
, cred_t
*credp
)
718 if ((error
= md_chk_uio(uio
)) != 0)
721 return (physio(mdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
));
726 md_trans_aread(dev_t dev
, struct aio_req
*aio
, cred_t
*credp
)
730 if ((error
= md_chk_uio(aio
->aio_uio
)) != 0)
733 return (aphysio(mdstrategy
, anocancel
, dev
, B_READ
, minphys
, aio
));
738 md_trans_write(dev_t dev
, struct uio
*uio
, cred_t
*credp
)
742 if ((error
= md_chk_uio(uio
)) != 0)
745 return (physio(mdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
));
750 md_trans_awrite(dev_t dev
, struct aio_req
*aio
, cred_t
*credp
)
754 if ((error
= md_chk_uio(aio
->aio_uio
)) != 0)
757 return (aphysio(mdstrategy
, anocancel
, dev
, B_WRITE
, minphys
, aio
));
761 trans_cleanup(mt_unit_t
*un
)
765 MD_STATUS(un
) |= MD_UN_LOG_DELETED
;
768 /* Save the mstr key */
769 sv
.setno
= MD_UN2SET(un
);
770 sv
.key
= un
->un_m_key
;
772 mddb_deleterec_wrapper(un
->c
.un_record_id
);
774 md_rem_names(&sv
, 1);
778 trans_snarf(md_snarfcmd_t cmd
, set_t setno
)
785 int all_trans_gotten
;
789 static int trans_found
= 0;
793 if (cmd
== MD_SNARF_CLEANUP
) {
795 if (md_get_setstatus(setno
) & MD_SET_STALE
)
799 * clean up partially cleared trans devices
801 typ1
= (mddb_type_t
)md_getshared_key(setno
,
802 trans_md_ops
.md_driver
.md_drivername
);
803 recid
= mddb_makerecid(setno
, 0);
804 while ((recid
= mddb_getnextrec(recid
, typ1
, TRANS_REC
)) > 0) {
805 un
= (mt_unit_t
*)mddb_getrecaddr(recid
);
806 (void) trans_detach(un
, 1);
807 if (mddb_getrecprivate(recid
) & MD_PRV_CLEANUP
) {
809 recid
= mddb_makerecid(setno
, 0);
813 * clean up partially cleared log devices
815 recid
= mddb_makerecid(setno
, 0);
816 while ((recid
= mddb_getnextrec(recid
, typ1
, LOG_REC
)) > 0) {
817 if (mddb_getrecprivate(recid
) & MD_PRV_CLEANUP
) {
818 ul
= (ml_unit_t
*)mddb_getrecaddr(recid
);
820 recid
= mddb_makerecid(setno
, 0);
828 * must snarf up the log devices first
831 all_trans_gotten
= 1;
832 typ1
= (mddb_type_t
)md_getshared_key(setno
,
833 trans_md_ops
.md_driver
.md_drivername
);
834 recid
= mddb_makerecid(setno
, 0);
835 while ((recid
= mddb_getnextrec(recid
, typ1
, LOG_REC
)) > 0) {
837 ml_unit32_od_t
*small_ul
;
839 if (mddb_getrecprivate(recid
) & MD_PRV_GOTIT
)
842 small_ul
= (ml_unit32_od_t
*)mddb_getrecaddr(recid
);
843 dep
= mddb_getrecdep(recid
);
844 dep
->de_flags
= MDDB_F_TRANS_LOG
;
847 * As trans records are always old records,
848 * we have to check if this record already has been converted.
849 * We don't want to do that work twice.
851 if ((rbp
->rb_private
& MD_PRV_CONVD
) == 0) {
852 newreqsize
= sizeof (ml_unit_t
);
853 big_ul
= (ml_unit_t
*)kmem_zalloc(newreqsize
, KM_SLEEP
);
854 trans_log_convert((caddr_t
)small_ul
, (caddr_t
)big_ul
,
856 kmem_free(small_ul
, dep
->de_reqsize
);
858 * Update userdata and incore userdata
859 * incores are at the end of ul
861 dep
->de_rb_userdata_ic
= big_ul
;
862 dep
->de_rb_userdata
= big_ul
;
863 dep
->de_icreqsize
= newreqsize
;
864 rbp
->rb_private
|= MD_PRV_CONVD
;
867 /* already converted, just set the pointer */
868 ul
= dep
->de_rb_userdata
;
870 all_trans_gotten
= 0;
871 if (ldl_build_incore(ul
, 1) == 0) {
872 mddb_setrecprivate(recid
, MD_PRV_GOTIT
);
878 * now snarf up metatrans devices
881 recid
= mddb_makerecid(setno
, 0);
882 while ((recid
= mddb_getnextrec(recid
, typ1
, TRANS_REC
)) > 0) {
884 mt_unit32_od_t
*small_un
;
886 if (mddb_getrecprivate(recid
) & MD_PRV_GOTIT
)
889 if ((trans_found
== 0) && (!MD_UPGRADE
)) {
890 cmn_err(CE_WARN
, MD_EOF_TRANS_MSG MD_EOF_TRANS_WARNING
);
894 small_un
= (mt_unit32_od_t
*)mddb_getrecaddr(recid
);
896 dep
= mddb_getrecdep(recid
);
897 dep
->de_flags
= MDDB_F_TRANS_MASTER
;
900 * As trans records are always old records,
901 * we have to check if this record already has been converted.
902 * We don't want to do that work twice.
904 if ((rbp
->rb_private
& MD_PRV_CONVD
) == 0) {
905 newreqsize
= sizeof (mt_unit_t
);
906 big_un
= (mt_unit_t
*)kmem_zalloc(newreqsize
, KM_SLEEP
);
907 trans_master_convert((caddr_t
)small_un
, (caddr_t
)big_un
,
909 kmem_free(small_un
, dep
->de_reqsize
);
911 * Update userdata and incore userdata
912 * incores are at the end of ul
914 dep
->de_rb_userdata_ic
= big_un
;
915 dep
->de_rb_userdata
= big_un
;
916 dep
->de_icreqsize
= newreqsize
;
917 rbp
->rb_private
|= MD_PRV_CONVD
;
919 un
->c
.un_revision
&= ~MD_64BIT_META_DEV
;
921 /* already converted, just set the pointer */
922 un
= dep
->de_rb_userdata
;
926 * Create minor node for snarfed entry.
928 (void) md_create_minor_node(MD_MIN2SET(MD_SID(un
)), MD_SID(un
));
930 if (MD_UNIT(MD_SID(un
)) != NULL
) {
931 mddb_setrecprivate(recid
, MD_PRV_PENDDEL
);
935 all_trans_gotten
= 0;
936 if (trans_build_incore(un
, 1) == 0) {
937 mddb_setrecprivate(recid
, MD_PRV_GOTIT
);
938 md_create_unit_incore(MD_SID(un
), &trans_md_ops
, 0);
943 if (!all_trans_gotten
)
944 return (gotsomething
);
946 recid
= mddb_makerecid(setno
, 0);
947 while ((recid
= mddb_getnextrec(recid
, typ1
, 0)) > 0)
948 if (!(mddb_getrecprivate(recid
) & MD_PRV_GOTIT
))
949 mddb_setrecprivate(recid
, MD_PRV_PENDDEL
);
954 trans_halt(md_haltcmd_t cmd
, set_t setno
)
961 if (cmd
== MD_HALT_CLOSE
) {
962 for (i
= 0; i
< md_nunits
; i
++) {
963 mnum
= MD_MKMIN(setno
, i
);
964 if ((ui
= MDI_UNIT(mnum
)) == NULL
)
966 if (ui
->ui_opsindex
!= trans_md_ops
.md_selfindex
)
968 if (md_unit_isopen(ui
)) {
972 for (i
= 0; i
< md_nunits
; i
++) {
973 mnum
= MD_MKMIN(setno
, i
);
974 if ((ui
= MDI_UNIT(mnum
)) == NULL
)
976 if (ui
->ui_opsindex
!= trans_md_ops
.md_selfindex
)
978 un
= (mt_unit_t
*)MD_UNIT(mnum
);
979 if ((un
->un_flags
& TRANS_NEED_OPEN
) == 0) {
980 trans_close_all_devs(un
);
986 if (cmd
== MD_HALT_OPEN
) {
987 for (i
= 0; i
< md_nunits
; i
++) {
988 mnum
= MD_MKMIN(setno
, i
);
989 if ((ui
= MDI_UNIT(mnum
)) == NULL
)
991 if (ui
->ui_opsindex
!= trans_md_ops
.md_selfindex
)
993 ldl_open_underlying((mt_unit_t
*)MD_UNIT(mnum
));
998 if (cmd
== MD_HALT_CHECK
) {
999 for (i
= 0; i
< md_nunits
; i
++) {
1000 mnum
= MD_MKMIN(setno
, i
);
1001 if ((ui
= MDI_UNIT(mnum
)) == NULL
)
1003 if (ui
->ui_opsindex
!= trans_md_ops
.md_selfindex
)
1005 if (md_unit_isopen(ui
)) {
1011 if (cmd
== MD_HALT_DOIT
) {
1012 for (i
= 0; i
< md_nunits
; i
++) {
1013 mnum
= MD_MKMIN(setno
, i
);
1014 if ((ui
= MDI_UNIT(mnum
)) == NULL
)
1016 if (ui
->ui_opsindex
!= trans_md_ops
.md_selfindex
)
1018 (void) trans_reset((mt_unit_t
*)MD_UNIT(mnum
), mnum
,
1023 if (cmd
== MD_HALT_UNLOAD
)
1039 minor_t mnum
= getminor(*dev
);
1040 mdi_unit_t
*ui
= MDI_UNIT(mnum
);
1044 /* disallow layered opens (e.g., PrestoServe) */
1045 if (otyp
== OTYP_LYR
)
1049 un
= (mt_unit_t
*)md_unit_openclose_enter(ui
);
1051 /* if already open, count open, return success */
1052 if (md_unit_isopen(ui
)) {
1053 err
= md_unit_incopen(mnum
, flag
, otyp
);
1054 md_unit_openclose_exit(ui
);
1061 * For some reason, not all of the metatrans devices attached to
1062 * this log were openable at snarf; try again now. All of the
1063 * underlying devices have to be openable for the roll thread to work.
1065 if (un
->un_flags
& TRANS_NEED_OPEN
) {
1066 md_unit_openclose_exit(ui
);
1067 ldl_open_underlying(un
);
1068 if (un
->un_flags
& TRANS_NEED_OPEN
)
1070 un
= (mt_unit_t
*)md_unit_openclose_enter(ui
);
1074 err
= md_unit_incopen(mnum
, flag
, otyp
);
1075 md_unit_openclose_exit(ui
);
1079 /* return success */
1093 minor_t mnum
= getminor(dev
);
1094 mdi_unit_t
*ui
= MDI_UNIT(mnum
);
1099 un
= (mt_unit_t
*)md_unit_openclose_enter(ui
);
1102 if ((err
= md_unit_decopen(mnum
, otyp
)) != 0) {
1103 md_unit_openclose_exit(ui
);
1108 if (md_unit_isopen(ui
)) {
1109 md_unit_openclose_exit(ui
);
1112 md_unit_openclose_exit(ui
);
1114 if (un
->un_flags
& TRANS_DETACHING
) {
1116 * prevent new opens and try to detach the log
1118 rw_enter(&md_unit_array_rw
.lock
, RW_WRITER
);
1119 (void) trans_detach(un
, 0);
1120 rw_exit(&md_unit_array_rw
.lock
);
1122 if (un
->un_flags
& TRANS_ATTACHING
) {
1124 * prevent new opens and try to attach the log
1126 rw_enter(&md_unit_array_rw
.lock
, RW_WRITER
);
1127 trans_attach(un
, 1);
1128 rw_exit(&md_unit_array_rw
.lock
);
1139 mt_unit32_od_t
*un32
;
1140 ml_unit32_od_t
*ul32
;
1142 int gotsomething
= 0;
1144 minor_t
*self_id
; /* minor needs to be updated */
1145 mddb_recid_t
*record_id
; /* record id needs to be updated */
1148 * Do log first if there is any
1149 * Note that trans record is always 32 bit
1151 typ1
= (mddb_type_t
)md_getshared_key(setno
,
1152 trans_md_ops
.md_driver
.md_drivername
);
1153 recid
= mddb_makerecid(setno
, 0);
1155 while ((recid
= mddb_getnextrec(recid
, typ1
, LOG_REC
)) > 0) {
1156 if (mddb_getrecprivate(recid
) & MD_PRV_GOTIT
)
1159 ul32
= (ml_unit32_od_t
*)mddb_getrecaddr(recid
);
1162 * Trans log record always is old format
1163 * Go ahead update the record with the new set info
1165 record_id
= &(ul32
->un_recid
);
1168 * Mark the record and update it
1170 *record_id
= MAKERECID(setno
, DBID(*record_id
));
1171 if (!md_update_minor(setno
, mddb_getsidenum
1172 (setno
), ul32
->un_key
))
1174 mddb_setrecprivate(recid
, MD_PRV_GOTIT
);
1181 recid
= mddb_makerecid(setno
, 0);
1182 while ((recid
= mddb_getnextrec(recid
, typ1
, TRANS_REC
)) > 0) {
1183 if (mddb_getrecprivate(recid
) & MD_PRV_GOTIT
)
1186 un32
= (mt_unit32_od_t
*)mddb_getrecaddr(recid
);
1189 * Trans master record always is old format
1191 self_id
= &(un32
->c
.un_self_id
);
1192 record_id
= &(un32
->c
.un_record_id
);
1195 * Mark the record and update it
1197 *record_id
= MAKERECID(setno
, DBID(*record_id
));
1198 *self_id
= MD_MKMIN(setno
, MD_MIN2UNIT(*self_id
));
1199 if (!md_update_minor(setno
, mddb_getsidenum
1200 (setno
), un32
->un_m_key
))
1202 mddb_setrecprivate(recid
, MD_PRV_GOTIT
);
1208 return (gotsomething
);
1211 static md_named_services_t trans_named_services
[] = {
1212 {(intptr_t (*)()) trans_rename_listkids
, MDRNM_LIST_URKIDS
},
1213 {(intptr_t (*)()) trans_rename_check
, MDRNM_CHECK
},
1214 {(intptr_t (*)()) trans_renexch_update_kids
, MDRNM_UPDATE_KIDS
},
1215 {(intptr_t (*)()) trans_rename_update_self
, MDRNM_UPDATE_SELF
},
1216 {(intptr_t (*)()) trans_exchange_self_update_from_down
,
1217 MDRNM_SELF_UPDATE_FROM_DOWN
},
1218 {(intptr_t (*)()) trans_exchange_parent_update_to
,
1219 MDRNM_PARENT_UPDATE_TO
},
1223 md_ops_t trans_md_ops
= {
1224 trans_open
, /* open */
1225 trans_close
, /* close */
1226 md_trans_strategy
, /* strategy */
1229 md_trans_read
, /* read */
1230 md_trans_write
, /* write */
1231 md_trans_ioctl
, /* trans ioctl */
1232 trans_snarf
, /* trans_snarf */
1233 trans_halt
, /* halt */
1234 md_trans_aread
, /* aread */
1235 md_trans_awrite
, /* awrite */
1236 trans_imp_set
, /* import set */
1237 trans_named_services
1244 ASSERT(_init_debug());
1245 trans_parent_cache
= kmem_cache_create("md_trans_parent",
1246 sizeof (md_tps_t
), 0, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
1247 trans_child_cache
= kmem_cache_create("md_trans_child", biosize(), 0,
1248 trans_child_constructor
, trans_child_destructor
,
1249 NULL
, NULL
, NULL
, 0);
1255 ASSERT(_fini_debug());
1257 kmem_cache_destroy(trans_parent_cache
);
1258 kmem_cache_destroy(trans_child_cache
);
1259 trans_parent_cache
= trans_child_cache
= NULL
;
1262 /* define the module linkage */
1263 MD_PLUGIN_MISC_MODULE("trans module", init_init(), fini_uninit())