1 #include <sys/modctl.h> 2 #include <sys/ddi.h> 3 #include <sys/sunddi.h> 4 #include <sys/devops.h> 5 #include <sys/conf.h> 6 #include <sys/cpuvar.h> 7 #include <sys/kobj.h> 8 #include <sys/spa.h> 9 #include <sys/arc.h> 10 #include <sys/vfs.h> 11 #include <sys/dnlc.h> 12 13 static dev_info_t *arcflushdevi; 14 15 #define FTAG ((char *)(uintptr_t)__func__) 16 17 static int arcflushioctl(dev_t dev, int cmd, intptr_t arg, int mode, 18 cred_t *credp, int *rvalp); 19 static int arcflushclose(dev_t dev, int flag, int otyp, cred_t *crepd); 20 static int arcflushopen(dev_t *devp, int flag, int otyp, cred_t *credp); 21 22 static struct cb_ops arcflush_cb_ops = { 23 arcflushopen, /* open */ 24 arcflushclose, /* close */ 25 nodev, /* strategy */ 26 nodev, /* print */ 27 nodev, /* dump */ 28 nodev, /* read */ 29 nodev, /* write */ 30 arcflushioctl, /* ioctl */ 31 nodev, /* devmap */ 32 nodev, /* mmap */ 33 nodev, /* segmap */ 34 nochpoll, /* poll */ 35 ddi_prop_op, /* prop_op */ 36 (struct streamtab *)0, /* streamtab */ 37 D_NEW | D_64BIT | D_MP, /* flags */ 38 CB_REV, 39 nodev, 40 nodev 41 }; 42 43 static int arcflushattach(dev_info_t *, ddi_attach_cmd_t); 44 static int arcflushdetach(dev_info_t *, ddi_detach_cmd_t); 45 static int arcflushinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 46 47 static struct dev_ops arcflush_ops = { 48 DEVO_REV, /* devo_rev */ 49 0, /* refcnt */ 50 arcflushinfo, /* info */ 51 nulldev, /* identify */ 52 nulldev, /* probe */ 53 arcflushattach, /* attach */ 54 arcflushdetach, /* detach */ 55 nodev, /* reset */ 56 &arcflush_cb_ops, /* driver operations */ 57 (struct bus_ops *)NULL, /* bus operations */ 58 NULL /* power */ 59 }; 60 61 static struct modldrv modldrv = { 62 &mod_driverops, /* type of module - a driver */ 63 "arcflush driver", 64 &arcflush_ops, 65 }; 66 67 static struct modlinkage modlinkage = { 68 MODREV_1, 69 { (void *)&modldrv, NULL } 70 }; 71 72 int 73 _init() 74 { 75 int error = mod_install(&modlinkage); 76 return (error); 77 } 78 79 int 80 _fini() 81 { 82 int error; 83 84 error = mod_remove(&modlinkage); 85 return (error); 86 } 87 88 int 89 _info(struct modinfo *modinfop) 90 { 91 int error; 92 93 error = mod_info(&modlinkage, modinfop); 94 return error; 95 } 96 97 static int 98 arcflushclose(dev_t dev, int flag, int otyp, cred_t *crepd) 99 { 100 if (otyp != OTYP_CHR) 101 return (EINVAL); 102 103 return (0); 104 } 105 106 static int 107 arcflushopen(dev_t *devp, int flag, int otyp, cred_t *credp) 108 { 109 if (otyp != OTYP_CHR) 110 return (EINVAL); 111 if (drv_priv(credp) != 0) 112 return (EPERM); 113 114 return (0); 115 } 116 117 static int 118 arcflushioctl(dev_t dev, int cmd, intptr_t arg, int mode, 119 cred_t *credp, int *rvalp) 120 { 121 spa_t *spa; 122 int ret; 123 char name[MAXPATHLEN + 1]; 124 vfs_t *vfsp; 125 126 if (ddi_copyin((void *)arg, name, MAXPATHLEN, mode) != 0) 127 return EFAULT; 128 name[MAXPATHLEN] = 0; 129 130 switch (cmd) { 131 case 0xf10053: 132 ret = spa_open(name, &spa, FTAG); 133 if (ret != 0) 134 return (ret); 135 arc_flush(spa, FALSE); 136 spa_close(spa, FTAG); 137 break; 138 case 0xf10054: 139 vfsp = vfs_mntpoint2vfsp(name); 140 if (vfsp == NULL) 141 return (EINVAL); 142 dnlc_purge_vfsp(vfsp, 0); 143 break; 144 default: 145 return ENOTTY; 146 } 147 148 return (0); 149 } 150 151 /*ARGSUSED*/ 152 static int 153 arcflushattach(dev_info_t *devi, ddi_attach_cmd_t cmd) 154 { 155 if (cmd != DDI_ATTACH) { 156 return (DDI_FAILURE); 157 } 158 159 if (ddi_create_minor_node(devi, "arcflush", S_IFCHR, 0, DDI_PSEUDO, 0) 160 == DDI_FAILURE) { 161 cmn_err(CE_NOTE, "arcflushattach fail: " 162 "ddi_create_minor_node\n"); 163 return (DDI_FAILURE); 164 } 165 ddi_report_dev(devi); 166 167 arcflushdevi = devi; 168 169 return (DDI_SUCCESS); 170 } 171 172 static int 173 arcflushdetach(dev_info_t *devi, ddi_detach_cmd_t cmd) 174 { 175 if (cmd != DDI_DETACH) { 176 return (DDI_FAILURE); 177 } 178 179 arcflushdevi = NULL; 180 181 ddi_prop_remove_all(devi); 182 ddi_remove_minor_node(devi, NULL); 183 184 return (DDI_SUCCESS); 185 } 186 187 /* ARGSUSED */ 188 static int 189 arcflushinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 190 { 191 int error; 192 switch (infocmd) { 193 case DDI_INFO_DEVT2DEVINFO: 194 *result = (void *)arcflushdevi; 195 error = DDI_SUCCESS; 196 break; 197 case DDI_INFO_DEVT2INSTANCE: 198 *result = (void *)0; 199 error = DDI_SUCCESS; 200 break; 201 default: 202 error = DDI_FAILURE; 203 } 204 return (error); 205 } 206