vfs_mount.c (99690) | vfs_mount.c (100363) |
---|---|
1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 47 unchanged lines hidden (view full) --- 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * | 1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 47 unchanged lines hidden (view full) --- 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * |
64 * $FreeBSD: head/sys/kern/vfs_mount.c 99690 2002-07-09 19:54:20Z jeff $ | 64 * $FreeBSD: head/sys/kern/vfs_mount.c 100363 2002-07-19 16:05:31Z mux $ |
65 */ 66 67#include <sys/param.h> 68#include <sys/conf.h> 69#include <sys/cons.h> 70#include <sys/kernel.h> 71#include <sys/linker.h> 72#include <sys/malloc.h> --- 67 unchanged lines hidden (view full) --- 140 NULL 141}; 142 143/* legacy find-root code */ 144char *rootdevnames[2] = {NULL, NULL}; 145static int setrootbyname(char *name); 146dev_t rootdev = NODEV; 147 | 65 */ 66 67#include <sys/param.h> 68#include <sys/conf.h> 69#include <sys/cons.h> 70#include <sys/kernel.h> 71#include <sys/linker.h> 72#include <sys/malloc.h> --- 67 unchanged lines hidden (view full) --- 140 NULL 141}; 142 143/* legacy find-root code */ 144char *rootdevnames[2] = {NULL, NULL}; 145static int setrootbyname(char *name); 146dev_t rootdev = NODEV; 147 |
148/* 149 * Release all resources related to the 150 * mount options. 151 */ | 148/* Remove one mount option. */ |
152static void | 149static void |
150vfs_freeopt(struct vfsoptlist *opts, struct vfsopt *opt) 151{ 152 153 TAILQ_REMOVE(opts, opt, link); 154 free(opt->name, M_MOUNT); 155 if (opt->value != NULL) 156 free(opt->value, M_MOUNT); 157#ifdef INVARIANTS 158 else if (opt->len != 0) 159 panic("%s: mount option with NULL value but length != 0", 160 __func__); 161#endif 162 free(opt, M_MOUNT); 163} 164 165/* Release all resources related to the mount options. */ 166static void |
|
153vfs_freeopts(struct vfsoptlist *opts) 154{ 155 struct vfsopt *opt; 156 157 while (!TAILQ_EMPTY(opts)) { 158 opt = TAILQ_FIRST(opts); | 167vfs_freeopts(struct vfsoptlist *opts) 168{ 169 struct vfsopt *opt; 170 171 while (!TAILQ_EMPTY(opts)) { 172 opt = TAILQ_FIRST(opts); |
159 TAILQ_REMOVE(opts, opt, link); 160 free(opt->name, M_MOUNT); 161 free(opt->value, M_MOUNT); 162 free(opt, M_MOUNT); | 173 vfs_freeopt(opts, opt); |
163 } 164 free(opts, M_MOUNT); 165} 166 167/* | 174 } 175 free(opts, M_MOUNT); 176} 177 178/* |
179 * If a mount option is specified several times, 180 * (with or without the "no" prefix) only keep 181 * the last occurence of it. 182 */ 183static void 184vfs_sanitizeopts(struct vfsoptlist *opts) 185{ 186 struct vfsopt *opt, *opt2, *tmp; 187 int noopt; 188 189 TAILQ_FOREACH_REVERSE(opt, opts, vfsoptlist, link) { 190 if (strncmp(opt->name, "no", 2) == 0) 191 noopt = 1; 192 else 193 noopt = 0; 194 opt2 = TAILQ_PREV(opt, vfsoptlist, link); 195 while (opt2 != NULL) { 196 if (strcmp(opt2->name, opt->name) == 0 || 197 (noopt && strcmp(opt->name + 2, opt2->name) == 0) || 198 (!noopt && strncmp(opt2->name, "no", 2) == 0 && 199 strcmp(opt2->name + 2, opt->name) == 0)) { 200 tmp = TAILQ_PREV(opt2, vfsoptlist, link); 201 vfs_freeopt(opts, opt2); 202 opt2 = tmp; 203 } else { 204 opt2 = TAILQ_PREV(opt2, vfsoptlist, link); 205 } 206 } 207 } 208} 209 210/* |
|
168 * Build a linked list of mount options from a struct uio. 169 */ 170static int 171vfs_buildopts(struct uio *auio, struct vfsoptlist **options) 172{ 173 struct vfsoptlist *opts; 174 struct vfsopt *opt; 175 unsigned int i, iovcnt; 176 int error, namelen, optlen; 177 178 iovcnt = auio->uio_iovcnt; 179 opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK); 180 TAILQ_INIT(opts); 181 for (i = 0; i < iovcnt; i += 2) { 182 opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK); 183 namelen = auio->uio_iov[i].iov_len; 184 optlen = auio->uio_iov[i + 1].iov_len; 185 opt->name = malloc(namelen, M_MOUNT, M_WAITOK); | 211 * Build a linked list of mount options from a struct uio. 212 */ 213static int 214vfs_buildopts(struct uio *auio, struct vfsoptlist **options) 215{ 216 struct vfsoptlist *opts; 217 struct vfsopt *opt; 218 unsigned int i, iovcnt; 219 int error, namelen, optlen; 220 221 iovcnt = auio->uio_iovcnt; 222 opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK); 223 TAILQ_INIT(opts); 224 for (i = 0; i < iovcnt; i += 2) { 225 opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK); 226 namelen = auio->uio_iov[i].iov_len; 227 optlen = auio->uio_iov[i + 1].iov_len; 228 opt->name = malloc(namelen, M_MOUNT, M_WAITOK); |
186 opt->value = malloc(optlen, M_MOUNT, M_WAITOK); | |
187 opt->len = optlen; | 229 opt->len = optlen; |
188 if (auio->uio_segflg == UIO_SYSSPACE) { 189 bcopy(auio->uio_iov[i].iov_base, opt->name, namelen); 190 bcopy(auio->uio_iov[i + 1].iov_base, opt->value, 191 optlen); | 230 if (optlen == 0) { 231 opt->value = NULL; |
192 } else { | 232 } else { |
193 error = copyin(auio->uio_iov[i].iov_base, opt->name, 194 namelen); 195 if (!error) | 233 opt->value = malloc(optlen, M_MOUNT, M_WAITOK); 234 if (auio->uio_segflg == UIO_SYSSPACE) { 235 bcopy(auio->uio_iov[i].iov_base, opt->name, 236 namelen); 237 bcopy(auio->uio_iov[i + 1].iov_base, opt->value, 238 optlen); 239 } else { 240 error = copyin(auio->uio_iov[i].iov_base, 241 opt->name, namelen); 242 if (error) 243 goto bad; |
196 error = copyin(auio->uio_iov[i + 1].iov_base, 197 opt->value, optlen); | 244 error = copyin(auio->uio_iov[i + 1].iov_base, 245 opt->value, optlen); |
198 if (error) 199 goto bad; | 246 if (error) 247 goto bad; 248 } |
200 } 201 TAILQ_INSERT_TAIL(opts, opt, link); 202 } | 249 } 250 TAILQ_INSERT_TAIL(opts, opt, link); 251 } |
252 vfs_sanitizeopts(opts); |
|
203 *options = opts; 204 return (0); 205bad: 206 vfs_freeopts(opts); 207 return (error); 208} 209 210/* | 253 *options = opts; 254 return (0); 255bad: 256 vfs_freeopts(opts); 257 return (error); 258} 259 260/* |
261 * Merge the old mount options with the new ones passed 262 * in the MNT_UPDATE case. 263 */ 264static void 265vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *opts) 266{ 267 struct vfsopt *opt, *opt2, *new; 268 269 TAILQ_FOREACH(opt, opts, link) { 270 /* 271 * Check that this option hasn't been redefined 272 * nor cancelled with a "no" mount option. 273 */ 274 opt2 = TAILQ_FIRST(toopts); 275 while (opt2 != NULL) { 276 if (strcmp(opt2->name, opt->name) == 0) 277 goto next; 278 if (strncmp(opt2->name, "no", 2) == 0 && 279 strcmp(opt2->name + 2, opt->name) == 0) { 280 vfs_freeopt(toopts, opt2); 281 goto next; 282 } 283 opt2 = TAILQ_NEXT(opt2, link); 284 } 285 /* We want this option, duplicate it. */ 286 new = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK); 287 new->name = malloc(strlen(opt->name) + 1, M_MOUNT, M_WAITOK); 288 strcpy(new->name, opt->name); 289 if (opt->len != 0) { 290 new->value = malloc(opt->len, M_MOUNT, M_WAITOK); 291 bcopy(opt->value, new->value, opt->len); 292 } else { 293 new->value = NULL; 294 } 295 new->len = opt->len; 296 TAILQ_INSERT_TAIL(toopts, new, link); 297next: 298 continue; 299 } 300} 301 302/* |
|
211 * New mount API. 212 */ 213int 214nmount(td, uap) 215 struct thread *td; 216 struct nmount_args /* { 217 syscallarg(struct iovec *) iovp; 218 syscallarg(unsigned int) iovcnt; --- 233 unchanged lines hidden (view full) --- 452 error = EBUSY; 453 goto bad; 454 } 455 vp->v_flag |= VMOUNT; 456 mtx_unlock(&vp->v_interlock); 457 mp->mnt_flag |= fsflags & 458 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT); 459 VOP_UNLOCK(vp, 0, td); | 303 * New mount API. 304 */ 305int 306nmount(td, uap) 307 struct thread *td; 308 struct nmount_args /* { 309 syscallarg(struct iovec *) iovp; 310 syscallarg(unsigned int) iovcnt; --- 233 unchanged lines hidden (view full) --- 544 error = EBUSY; 545 goto bad; 546 } 547 vp->v_flag |= VMOUNT; 548 mtx_unlock(&vp->v_interlock); 549 mp->mnt_flag |= fsflags & 550 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT); 551 VOP_UNLOCK(vp, 0, td); |
552 mp->mnt_optnew = optlist; 553 vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt); |
|
460 goto update; 461 } 462 /* 463 * If the user is not root, ensure that they own the directory 464 * onto which we are attempting to mount. 465 */ 466 error = VOP_GETATTR(vp, &va, td->td_ucred, td); 467 if (error) { --- 76 unchanged lines hidden (view full) --- 544 mp->mnt_stat.f_type = vfsp->vfc_typenum; 545 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 546 strncpy(mp->mnt_stat.f_fstypename, fstype, MFSNAMELEN); 547 mp->mnt_vnodecovered = vp; 548 mp->mnt_stat.f_owner = td->td_ucred->cr_uid; 549 strncpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN); 550 mp->mnt_iosize_max = DFLTPHYS; 551 VOP_UNLOCK(vp, 0, td); | 554 goto update; 555 } 556 /* 557 * If the user is not root, ensure that they own the directory 558 * onto which we are attempting to mount. 559 */ 560 error = VOP_GETATTR(vp, &va, td->td_ucred, td); 561 if (error) { --- 76 unchanged lines hidden (view full) --- 638 mp->mnt_stat.f_type = vfsp->vfc_typenum; 639 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 640 strncpy(mp->mnt_stat.f_fstypename, fstype, MFSNAMELEN); 641 mp->mnt_vnodecovered = vp; 642 mp->mnt_stat.f_owner = td->td_ucred->cr_uid; 643 strncpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN); 644 mp->mnt_iosize_max = DFLTPHYS; 645 VOP_UNLOCK(vp, 0, td); |
646 mp->mnt_optnew = optlist; |
|
552 553update: | 647 648update: |
554 mp->mnt_optnew = optlist; | |
555 /* 556 * Check if the fs implements the new VFS_NMOUNT() 557 * function, since the new system call was used. 558 */ 559 if (mp->mnt_op->vfs_mount != NULL) { 560 printf("%s doesn't support the new mount syscall\n", 561 mp->mnt_vfc->vfc_name); 562 mtx_lock(&vp->v_interlock); --- 1055 unchanged lines hidden --- | 649 /* 650 * Check if the fs implements the new VFS_NMOUNT() 651 * function, since the new system call was used. 652 */ 653 if (mp->mnt_op->vfs_mount != NULL) { 654 printf("%s doesn't support the new mount syscall\n", 655 mp->mnt_vfc->vfc_name); 656 mtx_lock(&vp->v_interlock); --- 1055 unchanged lines hidden --- |