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 struct modctl *ctl; 156 uint64_t diff; 157 struct patchlist *p; 158 int os_found; 159 int i; 160 161 if (cmd != DDI_ATTACH) { 162 return (DDI_FAILURE); 163 } 164 165 if (ddi_create_minor_node(devi, "arcflush", S_IFCHR, 0, DDI_PSEUDO, 0) 166 == DDI_FAILURE) { 167 cmn_err(CE_NOTE, "arcflushattach fail: " 168 "ddi_create_minor_node\n"); 169 return (DDI_FAILURE); 170 } 171 ddi_report_dev(devi); 172 173 arcflushdevi = devi; 174 175 return (DDI_SUCCESS); 176 } 177 178 static int 179 arcflushdetach(dev_info_t *devi, ddi_detach_cmd_t cmd) 180 { 181 struct patchlist *p; 182 183 if (cmd != DDI_DETACH) { 184 return (DDI_FAILURE); 185 } 186 187 arcflushdevi = NULL; 188 189 ddi_prop_remove_all(devi); 190 ddi_remove_minor_node(devi, NULL); 191 192 return (DDI_SUCCESS); 193 } 194 195 /* ARGSUSED */ 196 static int 197 arcflushinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 198 { 199 int error; 200 switch (infocmd) { 201 case DDI_INFO_DEVT2DEVINFO: 202 *result = (void *)arcflushdevi; 203 error = DDI_SUCCESS; 204 break; 205 case DDI_INFO_DEVT2INSTANCE: 206 *result = (void *)0; 207 error = DDI_SUCCESS; 208 break; 209 default: 210 error = DDI_FAILURE; 211 } 212 return (error); 213 } 214