Deleted Added
full compact
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 ---