Sat Nov 2 10:30:18 2013 UTC ()
Stop using v_mount of an unreferenced vnode -- save the mount while
the vnode has a reference.


(hannken)
diff -r1.86 -r1.87 src/sys/fs/msdosfs/msdosfs_vnops.c

cvs diff -r1.86 -r1.87 src/sys/fs/msdosfs/msdosfs_vnops.c (expand / switch to unified diff)

--- src/sys/fs/msdosfs/msdosfs_vnops.c 2013/03/18 19:35:37 1.86
+++ src/sys/fs/msdosfs/msdosfs_vnops.c 2013/11/02 10:30:18 1.87
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: msdosfs_vnops.c,v 1.86 2013/03/18 19:35:37 plunky Exp $ */ 1/* $NetBSD: msdosfs_vnops.c,v 1.87 2013/11/02 10:30:18 hannken Exp $ */
2 2
3/*- 3/*-
4 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 4 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
5 * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 5 * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
6 * All rights reserved. 6 * All rights reserved.
7 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 7 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -38,27 +38,27 @@ @@ -38,27 +38,27 @@
38 * it, and don't remove this notice. 38 * it, and don't remove this notice.
39 * 39 *
40 * This software is provided "as is". 40 * This software is provided "as is".
41 * 41 *
42 * The author supplies this software to be publicly redistributed on the 42 * The author supplies this software to be publicly redistributed on the
43 * understanding that the author is not responsible for the correct 43 * understanding that the author is not responsible for the correct
44 * functioning of this software in any circumstances and is not liable for 44 * functioning of this software in any circumstances and is not liable for
45 * any damages caused by this software. 45 * any damages caused by this software.
46 * 46 *
47 * October 1992 47 * October 1992
48 */ 48 */
49 49
50#include <sys/cdefs.h> 50#include <sys/cdefs.h>
51__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.86 2013/03/18 19:35:37 plunky Exp $"); 51__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.87 2013/11/02 10:30:18 hannken Exp $");
52 52
53#include <sys/param.h> 53#include <sys/param.h>
54#include <sys/systm.h> 54#include <sys/systm.h>
55#include <sys/namei.h> 55#include <sys/namei.h>
56#include <sys/resourcevar.h> /* defines plimit structure in proc struct */ 56#include <sys/resourcevar.h> /* defines plimit structure in proc struct */
57#include <sys/kernel.h> 57#include <sys/kernel.h>
58#include <sys/file.h> /* define FWRITE ... */ 58#include <sys/file.h> /* define FWRITE ... */
59#include <sys/stat.h> 59#include <sys/stat.h>
60#include <sys/buf.h> 60#include <sys/buf.h>
61#include <sys/proc.h> 61#include <sys/proc.h>
62#include <sys/mount.h> 62#include <sys/mount.h>
63#include <sys/fstrans.h> 63#include <sys/fstrans.h>
64#include <sys/vnode.h> 64#include <sys/vnode.h>
@@ -819,26 +819,27 @@ msdosfs_rename(void *v) @@ -819,26 +819,27 @@ msdosfs_rename(void *v)
819{ 819{
820 struct vop_rename_args /* { 820 struct vop_rename_args /* {
821 struct vnode *a_fdvp; 821 struct vnode *a_fdvp;
822 struct vnode *a_fvp; 822 struct vnode *a_fvp;
823 struct componentname *a_fcnp; 823 struct componentname *a_fcnp;
824 struct vnode *a_tdvp; 824 struct vnode *a_tdvp;
825 struct vnode *a_tvp; 825 struct vnode *a_tvp;
826 struct componentname *a_tcnp; 826 struct componentname *a_tcnp;
827 } */ *ap = v; 827 } */ *ap = v;
828 struct vnode *tvp = ap->a_tvp; 828 struct vnode *tvp = ap->a_tvp;
829 struct vnode *tdvp = ap->a_tdvp; 829 struct vnode *tdvp = ap->a_tdvp;
830 struct vnode *fvp = ap->a_fvp; 830 struct vnode *fvp = ap->a_fvp;
831 struct vnode *fdvp = ap->a_fdvp; 831 struct vnode *fdvp = ap->a_fdvp;
 832 struct mount *mp = fdvp->v_mount;
832 struct componentname *tcnp = ap->a_tcnp; 833 struct componentname *tcnp = ap->a_tcnp;
833 struct componentname *fcnp = ap->a_fcnp; 834 struct componentname *fcnp = ap->a_fcnp;
834 struct denode *ip, *xp, *dp, *zp; 835 struct denode *ip, *xp, *dp, *zp;
835 u_char toname[12], oldname[12]; 836 u_char toname[12], oldname[12];
836 u_long from_diroffset, to_diroffset; 837 u_long from_diroffset, to_diroffset;
837 u_char to_count; 838 u_char to_count;
838 int doingdirectory = 0, newparent = 0; 839 int doingdirectory = 0, newparent = 0;
839 int error; 840 int error;
840 u_long cn; 841 u_long cn;
841 daddr_t bn; 842 daddr_t bn;
842 struct msdosfsmount *pmp; 843 struct msdosfsmount *pmp;
843 struct direntry *dotdotp; 844 struct direntry *dotdotp;
844 struct buf *bp; 845 struct buf *bp;
@@ -896,27 +897,27 @@ abortit: @@ -896,27 +897,27 @@ abortit:
896 dp == ip || 897 dp == ip ||
897 (fcnp->cn_flags & ISDOTDOT) || 898 (fcnp->cn_flags & ISDOTDOT) ||
898 (tcnp->cn_flags & ISDOTDOT) || 899 (tcnp->cn_flags & ISDOTDOT) ||
899 (ip->de_flag & DE_RENAME)) { 900 (ip->de_flag & DE_RENAME)) {
900 VOP_UNLOCK(fvp); 901 VOP_UNLOCK(fvp);
901 error = EINVAL; 902 error = EINVAL;
902 goto abortit; 903 goto abortit;
903 } 904 }
904 ip->de_flag |= DE_RENAME; 905 ip->de_flag |= DE_RENAME;
905 doingdirectory++; 906 doingdirectory++;
906 } 907 }
907 VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */ 908 VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */
908 909
909 fstrans_start(fdvp->v_mount, FSTRANS_SHARED); 910 fstrans_start(mp, FSTRANS_SHARED);
910 /* 911 /*
911 * When the target exists, both the directory 912 * When the target exists, both the directory
912 * and target vnodes are returned locked. 913 * and target vnodes are returned locked.
913 */ 914 */
914 dp = VTODE(tdvp); 915 dp = VTODE(tdvp);
915 xp = tvp ? VTODE(tvp) : NULL; 916 xp = tvp ? VTODE(tvp) : NULL;
916 /* 917 /*
917 * Remember direntry place to use for destination 918 * Remember direntry place to use for destination
918 */ 919 */
919 to_diroffset = dp->de_fndoffset; 920 to_diroffset = dp->de_fndoffset;
920 to_count = dp->de_fndcnt; 921 to_count = dp->de_fndcnt;
921 922
922 /* 923 /*
@@ -983,55 +984,55 @@ abortit: @@ -983,55 +984,55 @@ abortit:
983 VN_KNOTE(tvp, NOTE_DELETE); 984 VN_KNOTE(tvp, NOTE_DELETE);
984 cache_purge(tvp); 985 cache_purge(tvp);
985 vput(tvp); 986 vput(tvp);
986 tvp = NULL; 987 tvp = NULL;
987 xp = NULL; 988 xp = NULL;
988 } 989 }
989 990
990 /* 991 /*
991 * Convert the filename in tcnp into a dos filename. We copy this 992 * Convert the filename in tcnp into a dos filename. We copy this
992 * into the denode and directory entry for the destination 993 * into the denode and directory entry for the destination
993 * file/directory. 994 * file/directory.
994 */ 995 */
995 if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) { 996 if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) {
996 fstrans_done(fdvp->v_mount); 997 fstrans_done(mp);
997 goto abortit; 998 goto abortit;
998 } 999 }
999 1000
1000 /* 1001 /*
1001 * Since from wasn't locked at various places above, 1002 * Since from wasn't locked at various places above,
1002 * have to do a relookup here. 1003 * have to do a relookup here.
1003 */ 1004 */
1004 fcnp->cn_flags &= ~MODMASK; 1005 fcnp->cn_flags &= ~MODMASK;
1005 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 1006 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1006 VOP_UNLOCK(tdvp); 1007 VOP_UNLOCK(tdvp);
1007 vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); 1008 vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
1008 if ((error = relookup(fdvp, &fvp, fcnp, 0))) { 1009 if ((error = relookup(fdvp, &fvp, fcnp, 0))) {
1009 VOP_UNLOCK(fdvp); 1010 VOP_UNLOCK(fdvp);
1010 vrele(ap->a_fvp); 1011 vrele(ap->a_fvp);
1011 vrele(tdvp); 1012 vrele(tdvp);
1012 fstrans_done(fdvp->v_mount); 1013 fstrans_done(mp);
1013 return (error); 1014 return (error);
1014 } 1015 }
1015 if (fvp == NULL) { 1016 if (fvp == NULL) {
1016 /* 1017 /*
1017 * From name has disappeared. 1018 * From name has disappeared.
1018 */ 1019 */
1019 if (doingdirectory) 1020 if (doingdirectory)
1020 panic("rename: lost dir entry"); 1021 panic("rename: lost dir entry");
1021 vput(fdvp); 1022 vput(fdvp);
1022 vrele(ap->a_fvp); 1023 vrele(ap->a_fvp);
1023 vrele(tdvp); 1024 vrele(tdvp);
1024 fstrans_done(fdvp->v_mount); 1025 fstrans_done(mp);
1025 return 0; 1026 return 0;
1026 } 1027 }
1027 VOP_UNLOCK(fdvp); 1028 VOP_UNLOCK(fdvp);
1028 xp = VTODE(fvp); 1029 xp = VTODE(fvp);
1029 zp = VTODE(fdvp); 1030 zp = VTODE(fdvp);
1030 from_diroffset = zp->de_fndoffset; 1031 from_diroffset = zp->de_fndoffset;
1031 1032
1032 /* 1033 /*
1033 * Ensure that the directory entry still exists and has not 1034 * Ensure that the directory entry still exists and has not
1034 * changed till now. If the source is a file the entry may 1035 * changed till now. If the source is a file the entry may
1035 * have been unlinked or renamed. In either case there is 1036 * have been unlinked or renamed. In either case there is
1036 * no further work to be done. If the source is a directory 1037 * no further work to be done. If the source is a directory
1037 * then it cannot have been rmdir'ed or renamed; this is 1038 * then it cannot have been rmdir'ed or renamed; this is
@@ -1119,27 +1120,27 @@ abortit: @@ -1119,27 +1120,27 @@ abortit:
1119 goto bad; 1120 goto bad;
1120 } 1121 }
1121 } 1122 }
1122 1123
1123 VN_KNOTE(fvp, NOTE_RENAME); 1124 VN_KNOTE(fvp, NOTE_RENAME);
1124 VOP_UNLOCK(fvp); 1125 VOP_UNLOCK(fvp);
1125bad: 1126bad:
1126 if (tvp) 1127 if (tvp)
1127 vput(tvp); 1128 vput(tvp);
1128 vrele(tdvp); 1129 vrele(tdvp);
1129 ip->de_flag &= ~DE_RENAME; 1130 ip->de_flag &= ~DE_RENAME;
1130 vrele(fdvp); 1131 vrele(fdvp);
1131 vrele(fvp); 1132 vrele(fvp);
1132 fstrans_done(fdvp->v_mount); 1133 fstrans_done(mp);
1133 return (error); 1134 return (error);
1134 1135
1135 /* XXX: uuuh */ 1136 /* XXX: uuuh */
1136tdvpbad: 1137tdvpbad:
1137 VOP_UNLOCK(tdvp); 1138 VOP_UNLOCK(tdvp);
1138 goto bad; 1139 goto bad;
1139} 1140}
1140 1141
1141static const struct { 1142static const struct {
1142 struct direntry dot; 1143 struct direntry dot;
1143 struct direntry dotdot; 1144 struct direntry dotdot;
1144} dosdirtemplate = { 1145} dosdirtemplate = {
1145 { ". ", " ", /* the . entry */ 1146 { ". ", " ", /* the . entry */
@@ -1281,41 +1282,42 @@ bad2: @@ -1281,41 +1282,42 @@ bad2:
1281 return (error); 1282 return (error);
1282} 1283}
1283 1284
1284int 1285int
1285msdosfs_rmdir(void *v) 1286msdosfs_rmdir(void *v)
1286{ 1287{
1287 struct vop_rmdir_args /* { 1288 struct vop_rmdir_args /* {
1288 struct vnode *a_dvp; 1289 struct vnode *a_dvp;
1289 struct vnode *a_vp; 1290 struct vnode *a_vp;
1290 struct componentname *a_cnp; 1291 struct componentname *a_cnp;
1291 } */ *ap = v; 1292 } */ *ap = v;
1292 struct vnode *vp = ap->a_vp; 1293 struct vnode *vp = ap->a_vp;
1293 struct vnode *dvp = ap->a_dvp; 1294 struct vnode *dvp = ap->a_dvp;
 1295 struct mount *mp = dvp->v_mount;
1294 struct componentname *cnp = ap->a_cnp; 1296 struct componentname *cnp = ap->a_cnp;
1295 struct denode *ip, *dp; 1297 struct denode *ip, *dp;
1296 int error; 1298 int error;
1297 1299
1298 ip = VTODE(vp); 1300 ip = VTODE(vp);
1299 dp = VTODE(dvp); 1301 dp = VTODE(dvp);
1300 /* 1302 /*
1301 * No rmdir "." please. 1303 * No rmdir "." please.
1302 */ 1304 */
1303 if (dp == ip) { 1305 if (dp == ip) {
1304 vrele(dvp); 1306 vrele(dvp);
1305 vput(vp); 1307 vput(vp);
1306 return (EINVAL); 1308 return (EINVAL);
1307 } 1309 }
1308 fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); 1310 fstrans_start(mp, FSTRANS_SHARED);
1309 /* 1311 /*
1310 * Verify the directory is empty (and valid). 1312 * Verify the directory is empty (and valid).
1311 * (Rmdir ".." won't be valid since 1313 * (Rmdir ".." won't be valid since
1312 * ".." will contain a reference to 1314 * ".." will contain a reference to
1313 * the current directory and thus be 1315 * the current directory and thus be
1314 * non-empty.) 1316 * non-empty.)
1315 */ 1317 */
1316 error = 0; 1318 error = 0;
1317 if (!dosdirempty(ip) || ip->de_flag & DE_RENAME) { 1319 if (!dosdirempty(ip) || ip->de_flag & DE_RENAME) {
1318 error = ENOTEMPTY; 1320 error = ENOTEMPTY;
1319 goto out; 1321 goto out;
1320 } 1322 }
1321 /* 1323 /*
@@ -1337,27 +1339,27 @@ msdosfs_rmdir(void *v) @@ -1337,27 +1339,27 @@ msdosfs_rmdir(void *v)
1337 cache_purge(dvp); 1339 cache_purge(dvp);
1338 vput(dvp); 1340 vput(dvp);
1339 dvp = NULL; 1341 dvp = NULL;
1340 /* 1342 /*
1341 * Truncate the directory that is being deleted. 1343 * Truncate the directory that is being deleted.
1342 */ 1344 */
1343 error = detrunc(ip, (u_long)0, IO_SYNC, cnp->cn_cred); 1345 error = detrunc(ip, (u_long)0, IO_SYNC, cnp->cn_cred);
1344 cache_purge(vp); 1346 cache_purge(vp);
1345out: 1347out:
1346 VN_KNOTE(vp, NOTE_DELETE); 1348 VN_KNOTE(vp, NOTE_DELETE);
1347 if (dvp) 1349 if (dvp)
1348 vput(dvp); 1350 vput(dvp);
1349 vput(vp); 1351 vput(vp);
1350 fstrans_done(ap->a_dvp->v_mount); 1352 fstrans_done(mp);
1351 return (error); 1353 return (error);
1352} 1354}
1353 1355
1354int 1356int
1355msdosfs_readdir(void *v) 1357msdosfs_readdir(void *v)
1356{ 1358{
1357 struct vop_readdir_args /* { 1359 struct vop_readdir_args /* {
1358 struct vnode *a_vp; 1360 struct vnode *a_vp;
1359 struct uio *a_uio; 1361 struct uio *a_uio;
1360 kauth_cred_t a_cred; 1362 kauth_cred_t a_cred;
1361 int *a_eofflag; 1363 int *a_eofflag;
1362 off_t **a_cookies; 1364 off_t **a_cookies;
1363 int *a_ncookies; 1365 int *a_ncookies;