Deleted Added
full compact
vfs_cache.c (232420) vfs_cache.c (241896)
1/*-
2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Poul-Henning Kamp of the FreeBSD Project.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 19 unchanged lines hidden (view full) ---

28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
33 */
34
35#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Poul-Henning Kamp of the FreeBSD Project.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 19 unchanged lines hidden (view full) ---

28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/kern/vfs_cache.c 232420 2012-03-03 01:06:54Z rmacklem $");
36__FBSDID("$FreeBSD: head/sys/kern/vfs_cache.c 241896 2012-10-22 17:50:54Z kib $");
37
38#include "opt_kdtrace.h"
39#include "opt_ktrace.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/filedesc.h>
44#include <sys/fnv_hash.h>

--- 1019 unchanged lines hidden (view full) ---

1064}
1065
1066int
1067kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg, u_int buflen)
1068{
1069 char *bp, *tmpbuf;
1070 struct filedesc *fdp;
1071 struct vnode *cdir, *rdir;
37
38#include "opt_kdtrace.h"
39#include "opt_ktrace.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/filedesc.h>
44#include <sys/fnv_hash.h>

--- 1019 unchanged lines hidden (view full) ---

1064}
1065
1066int
1067kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg, u_int buflen)
1068{
1069 char *bp, *tmpbuf;
1070 struct filedesc *fdp;
1071 struct vnode *cdir, *rdir;
1072 int error, vfslocked;
1072 int error;
1073
1074 if (disablecwd)
1075 return (ENODEV);
1076 if (buflen < 2)
1077 return (EINVAL);
1078 if (buflen > MAXPATHLEN)
1079 buflen = MAXPATHLEN;
1080
1081 tmpbuf = malloc(buflen, M_TEMP, M_WAITOK);
1082 fdp = td->td_proc->p_fd;
1083 FILEDESC_SLOCK(fdp);
1084 cdir = fdp->fd_cdir;
1085 VREF(cdir);
1086 rdir = fdp->fd_rdir;
1087 VREF(rdir);
1088 FILEDESC_SUNLOCK(fdp);
1089 error = vn_fullpath1(td, cdir, rdir, tmpbuf, &bp, buflen);
1073
1074 if (disablecwd)
1075 return (ENODEV);
1076 if (buflen < 2)
1077 return (EINVAL);
1078 if (buflen > MAXPATHLEN)
1079 buflen = MAXPATHLEN;
1080
1081 tmpbuf = malloc(buflen, M_TEMP, M_WAITOK);
1082 fdp = td->td_proc->p_fd;
1083 FILEDESC_SLOCK(fdp);
1084 cdir = fdp->fd_cdir;
1085 VREF(cdir);
1086 rdir = fdp->fd_rdir;
1087 VREF(rdir);
1088 FILEDESC_SUNLOCK(fdp);
1089 error = vn_fullpath1(td, cdir, rdir, tmpbuf, &bp, buflen);
1090 vfslocked = VFS_LOCK_GIANT(rdir->v_mount);
1091 vrele(rdir);
1090 vrele(rdir);
1092 VFS_UNLOCK_GIANT(vfslocked);
1093 vfslocked = VFS_LOCK_GIANT(cdir->v_mount);
1094 vrele(cdir);
1091 vrele(cdir);
1095 VFS_UNLOCK_GIANT(vfslocked);
1096
1097 if (!error) {
1098 if (bufseg == UIO_SYSSPACE)
1099 bcopy(bp, buf, strlen(bp) + 1);
1100 else
1101 error = copyout(bp, buf, strlen(bp) + 1);
1102#ifdef KTRACE
1103 if (KTRPOINT(curthread, KTR_NAMEI))

--- 30 unchanged lines hidden (view full) ---

1134 * cache (if available)
1135 */
1136int
1137vn_fullpath(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf)
1138{
1139 char *buf;
1140 struct filedesc *fdp;
1141 struct vnode *rdir;
1092
1093 if (!error) {
1094 if (bufseg == UIO_SYSSPACE)
1095 bcopy(bp, buf, strlen(bp) + 1);
1096 else
1097 error = copyout(bp, buf, strlen(bp) + 1);
1098#ifdef KTRACE
1099 if (KTRPOINT(curthread, KTR_NAMEI))

--- 30 unchanged lines hidden (view full) ---

1130 * cache (if available)
1131 */
1132int
1133vn_fullpath(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf)
1134{
1135 char *buf;
1136 struct filedesc *fdp;
1137 struct vnode *rdir;
1142 int error, vfslocked;
1138 int error;
1143
1144 if (disablefullpath)
1145 return (ENODEV);
1146 if (vn == NULL)
1147 return (EINVAL);
1148
1149 buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1150 fdp = td->td_proc->p_fd;
1151 FILEDESC_SLOCK(fdp);
1152 rdir = fdp->fd_rdir;
1153 VREF(rdir);
1154 FILEDESC_SUNLOCK(fdp);
1155 error = vn_fullpath1(td, vn, rdir, buf, retbuf, MAXPATHLEN);
1139
1140 if (disablefullpath)
1141 return (ENODEV);
1142 if (vn == NULL)
1143 return (EINVAL);
1144
1145 buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1146 fdp = td->td_proc->p_fd;
1147 FILEDESC_SLOCK(fdp);
1148 rdir = fdp->fd_rdir;
1149 VREF(rdir);
1150 FILEDESC_SUNLOCK(fdp);
1151 error = vn_fullpath1(td, vn, rdir, buf, retbuf, MAXPATHLEN);
1156 vfslocked = VFS_LOCK_GIANT(rdir->v_mount);
1157 vrele(rdir);
1152 vrele(rdir);
1158 VFS_UNLOCK_GIANT(vfslocked);
1159
1160 if (!error)
1161 *freebuf = buf;
1162 else
1163 free(buf, M_TEMP);
1164 return (error);
1165}
1166

--- 36 unchanged lines hidden (view full) ---

1203}
1204
1205static int
1206vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, char *buf,
1207 u_int *buflen)
1208{
1209 struct vnode *dvp;
1210 struct namecache *ncp;
1153
1154 if (!error)
1155 *freebuf = buf;
1156 else
1157 free(buf, M_TEMP);
1158 return (error);
1159}
1160

--- 36 unchanged lines hidden (view full) ---

1197}
1198
1199static int
1200vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, char *buf,
1201 u_int *buflen)
1202{
1203 struct vnode *dvp;
1204 struct namecache *ncp;
1211 int error, vfslocked;
1205 int error;
1212
1213 TAILQ_FOREACH(ncp, &((*vp)->v_cache_dst), nc_dst) {
1214 if ((ncp->nc_flag & NCF_ISDOTDOT) == 0)
1215 break;
1216 }
1217 if (ncp != NULL) {
1218 if (*buflen < ncp->nc_nlen) {
1219 CACHE_RUNLOCK();
1206
1207 TAILQ_FOREACH(ncp, &((*vp)->v_cache_dst), nc_dst) {
1208 if ((ncp->nc_flag & NCF_ISDOTDOT) == 0)
1209 break;
1210 }
1211 if (ncp != NULL) {
1212 if (*buflen < ncp->nc_nlen) {
1213 CACHE_RUNLOCK();
1220 vfslocked = VFS_LOCK_GIANT((*vp)->v_mount);
1221 vrele(*vp);
1214 vrele(*vp);
1222 VFS_UNLOCK_GIANT(vfslocked);
1223 numfullpathfail4++;
1224 error = ENOMEM;
1225 SDT_PROBE(vfs, namecache, fullpath, return, error,
1226 vp, NULL, 0, 0);
1227 return (error);
1228 }
1229 *buflen -= ncp->nc_nlen;
1230 memcpy(buf + *buflen, nc_get_name(ncp), ncp->nc_nlen);
1231 SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp,
1232 nc_get_name(ncp), vp, 0, 0);
1233 dvp = *vp;
1234 *vp = ncp->nc_dvp;
1235 vref(*vp);
1236 CACHE_RUNLOCK();
1215 numfullpathfail4++;
1216 error = ENOMEM;
1217 SDT_PROBE(vfs, namecache, fullpath, return, error,
1218 vp, NULL, 0, 0);
1219 return (error);
1220 }
1221 *buflen -= ncp->nc_nlen;
1222 memcpy(buf + *buflen, nc_get_name(ncp), ncp->nc_nlen);
1223 SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp,
1224 nc_get_name(ncp), vp, 0, 0);
1225 dvp = *vp;
1226 *vp = ncp->nc_dvp;
1227 vref(*vp);
1228 CACHE_RUNLOCK();
1237 vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
1238 vrele(dvp);
1229 vrele(dvp);
1239 VFS_UNLOCK_GIANT(vfslocked);
1240 CACHE_RLOCK();
1241 return (0);
1242 }
1243 SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, 0, 0);
1244
1245 CACHE_RUNLOCK();
1230 CACHE_RLOCK();
1231 return (0);
1232 }
1233 SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, 0, 0);
1234
1235 CACHE_RUNLOCK();
1246 vfslocked = VFS_LOCK_GIANT((*vp)->v_mount);
1247 vn_lock(*vp, LK_SHARED | LK_RETRY);
1248 error = VOP_VPTOCNP(*vp, &dvp, cred, buf, buflen);
1249 vput(*vp);
1236 vn_lock(*vp, LK_SHARED | LK_RETRY);
1237 error = VOP_VPTOCNP(*vp, &dvp, cred, buf, buflen);
1238 vput(*vp);
1250 VFS_UNLOCK_GIANT(vfslocked);
1251 if (error) {
1252 numfullpathfail2++;
1253 SDT_PROBE(vfs, namecache, fullpath, return, error, vp,
1254 NULL, 0, 0);
1255 return (error);
1256 }
1257
1258 *vp = dvp;
1259 CACHE_RLOCK();
1260 if (dvp->v_iflag & VI_DOOMED) {
1261 /* forced unmount */
1262 CACHE_RUNLOCK();
1239 if (error) {
1240 numfullpathfail2++;
1241 SDT_PROBE(vfs, namecache, fullpath, return, error, vp,
1242 NULL, 0, 0);
1243 return (error);
1244 }
1245
1246 *vp = dvp;
1247 CACHE_RLOCK();
1248 if (dvp->v_iflag & VI_DOOMED) {
1249 /* forced unmount */
1250 CACHE_RUNLOCK();
1263 vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
1264 vrele(dvp);
1251 vrele(dvp);
1265 VFS_UNLOCK_GIANT(vfslocked);
1266 error = ENOENT;
1267 SDT_PROBE(vfs, namecache, fullpath, return, error, vp,
1268 NULL, 0, 0);
1269 return (error);
1270 }
1271 /*
1272 * *vp has its use count incremented still.
1273 */
1274
1275 return (0);
1276}
1277
1278/*
1279 * The magic behind kern___getcwd() and vn_fullpath().
1280 */
1281static int
1282vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
1283 char *buf, char **retbuf, u_int buflen)
1284{
1252 error = ENOENT;
1253 SDT_PROBE(vfs, namecache, fullpath, return, error, vp,
1254 NULL, 0, 0);
1255 return (error);
1256 }
1257 /*
1258 * *vp has its use count incremented still.
1259 */
1260
1261 return (0);
1262}
1263
1264/*
1265 * The magic behind kern___getcwd() and vn_fullpath().
1266 */
1267static int
1268vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
1269 char *buf, char **retbuf, u_int buflen)
1270{
1285 int error, slash_prefixed, vfslocked;
1271 int error, slash_prefixed;
1286#ifdef KDTRACE_HOOKS
1287 struct vnode *startvp = vp;
1288#endif
1289 struct vnode *vp1;
1290
1291 buflen--;
1292 buf[buflen] = '\0';
1293 error = 0;

--- 4 unchanged lines hidden (view full) ---

1298 vref(vp);
1299 CACHE_RLOCK();
1300 if (vp->v_type != VDIR) {
1301 error = vn_vptocnp_locked(&vp, td->td_ucred, buf, &buflen);
1302 if (error)
1303 return (error);
1304 if (buflen == 0) {
1305 CACHE_RUNLOCK();
1272#ifdef KDTRACE_HOOKS
1273 struct vnode *startvp = vp;
1274#endif
1275 struct vnode *vp1;
1276
1277 buflen--;
1278 buf[buflen] = '\0';
1279 error = 0;

--- 4 unchanged lines hidden (view full) ---

1284 vref(vp);
1285 CACHE_RLOCK();
1286 if (vp->v_type != VDIR) {
1287 error = vn_vptocnp_locked(&vp, td->td_ucred, buf, &buflen);
1288 if (error)
1289 return (error);
1290 if (buflen == 0) {
1291 CACHE_RUNLOCK();
1306 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1307 vrele(vp);
1292 vrele(vp);
1308 VFS_UNLOCK_GIANT(vfslocked);
1309 return (ENOMEM);
1310 }
1311 buf[--buflen] = '/';
1312 slash_prefixed = 1;
1313 }
1314 while (vp != rdir && vp != rootvnode) {
1315 if (vp->v_vflag & VV_ROOT) {
1316 if (vp->v_iflag & VI_DOOMED) { /* forced unmount */
1317 CACHE_RUNLOCK();
1293 return (ENOMEM);
1294 }
1295 buf[--buflen] = '/';
1296 slash_prefixed = 1;
1297 }
1298 while (vp != rdir && vp != rootvnode) {
1299 if (vp->v_vflag & VV_ROOT) {
1300 if (vp->v_iflag & VI_DOOMED) { /* forced unmount */
1301 CACHE_RUNLOCK();
1318 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1319 vrele(vp);
1302 vrele(vp);
1320 VFS_UNLOCK_GIANT(vfslocked);
1321 error = ENOENT;
1322 SDT_PROBE(vfs, namecache, fullpath, return,
1323 error, vp, NULL, 0, 0);
1324 break;
1325 }
1326 vp1 = vp->v_mount->mnt_vnodecovered;
1327 vref(vp1);
1328 CACHE_RUNLOCK();
1303 error = ENOENT;
1304 SDT_PROBE(vfs, namecache, fullpath, return,
1305 error, vp, NULL, 0, 0);
1306 break;
1307 }
1308 vp1 = vp->v_mount->mnt_vnodecovered;
1309 vref(vp1);
1310 CACHE_RUNLOCK();
1329 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1330 vrele(vp);
1311 vrele(vp);
1331 VFS_UNLOCK_GIANT(vfslocked);
1332 vp = vp1;
1333 CACHE_RLOCK();
1334 continue;
1335 }
1336 if (vp->v_type != VDIR) {
1337 CACHE_RUNLOCK();
1312 vp = vp1;
1313 CACHE_RLOCK();
1314 continue;
1315 }
1316 if (vp->v_type != VDIR) {
1317 CACHE_RUNLOCK();
1338 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1339 vrele(vp);
1318 vrele(vp);
1340 VFS_UNLOCK_GIANT(vfslocked);
1341 numfullpathfail1++;
1342 error = ENOTDIR;
1343 SDT_PROBE(vfs, namecache, fullpath, return,
1344 error, vp, NULL, 0, 0);
1345 break;
1346 }
1347 error = vn_vptocnp_locked(&vp, td->td_ucred, buf, &buflen);
1348 if (error)
1349 break;
1350 if (buflen == 0) {
1351 CACHE_RUNLOCK();
1319 numfullpathfail1++;
1320 error = ENOTDIR;
1321 SDT_PROBE(vfs, namecache, fullpath, return,
1322 error, vp, NULL, 0, 0);
1323 break;
1324 }
1325 error = vn_vptocnp_locked(&vp, td->td_ucred, buf, &buflen);
1326 if (error)
1327 break;
1328 if (buflen == 0) {
1329 CACHE_RUNLOCK();
1352 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1353 vrele(vp);
1330 vrele(vp);
1354 VFS_UNLOCK_GIANT(vfslocked);
1355 error = ENOMEM;
1356 SDT_PROBE(vfs, namecache, fullpath, return, error,
1357 startvp, NULL, 0, 0);
1358 break;
1359 }
1360 buf[--buflen] = '/';
1361 slash_prefixed = 1;
1362 }
1363 if (error)
1364 return (error);
1365 if (!slash_prefixed) {
1366 if (buflen == 0) {
1367 CACHE_RUNLOCK();
1331 error = ENOMEM;
1332 SDT_PROBE(vfs, namecache, fullpath, return, error,
1333 startvp, NULL, 0, 0);
1334 break;
1335 }
1336 buf[--buflen] = '/';
1337 slash_prefixed = 1;
1338 }
1339 if (error)
1340 return (error);
1341 if (!slash_prefixed) {
1342 if (buflen == 0) {
1343 CACHE_RUNLOCK();
1368 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1369 vrele(vp);
1344 vrele(vp);
1370 VFS_UNLOCK_GIANT(vfslocked);
1371 numfullpathfail4++;
1372 SDT_PROBE(vfs, namecache, fullpath, return, ENOMEM,
1373 startvp, NULL, 0, 0);
1374 return (ENOMEM);
1375 }
1376 buf[--buflen] = '/';
1377 }
1378 numfullpathfound++;
1379 CACHE_RUNLOCK();
1345 numfullpathfail4++;
1346 SDT_PROBE(vfs, namecache, fullpath, return, ENOMEM,
1347 startvp, NULL, 0, 0);
1348 return (ENOMEM);
1349 }
1350 buf[--buflen] = '/';
1351 }
1352 numfullpathfound++;
1353 CACHE_RUNLOCK();
1380 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1381 vrele(vp);
1354 vrele(vp);
1382 VFS_UNLOCK_GIANT(vfslocked);
1383
1384 SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, buf + buflen,
1385 0, 0);
1386 *retbuf = buf + buflen;
1387 return (0);
1388}
1389
1390int

--- 45 unchanged lines hidden (view full) ---

1436 */
1437int
1438vn_path_to_global_path(struct thread *td, struct vnode *vp, char *path,
1439 u_int pathlen)
1440{
1441 struct nameidata nd;
1442 struct vnode *vp1;
1443 char *rpath, *fbuf;
1355
1356 SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, buf + buflen,
1357 0, 0);
1358 *retbuf = buf + buflen;
1359 return (0);
1360}
1361
1362int

--- 45 unchanged lines hidden (view full) ---

1408 */
1409int
1410vn_path_to_global_path(struct thread *td, struct vnode *vp, char *path,
1411 u_int pathlen)
1412{
1413 struct nameidata nd;
1414 struct vnode *vp1;
1415 char *rpath, *fbuf;
1444 int error, vfslocked;
1416 int error;
1445
1417
1446 VFS_ASSERT_GIANT(vp->v_mount);
1447 ASSERT_VOP_ELOCKED(vp, __func__);
1448
1449 /* Return ENODEV if sysctl debug.disablefullpath==1 */
1450 if (disablefullpath)
1451 return (ENODEV);
1452
1453 /* Construct global filesystem path from vp. */
1454 VOP_UNLOCK(vp, 0);

--- 10 unchanged lines hidden (view full) ---

1465 goto out;
1466 }
1467
1468 /*
1469 * Re-lookup the vnode by path to detect a possible rename.
1470 * As a side effect, the vnode is relocked.
1471 * If vnode was renamed, return ENOENT.
1472 */
1418 ASSERT_VOP_ELOCKED(vp, __func__);
1419
1420 /* Return ENODEV if sysctl debug.disablefullpath==1 */
1421 if (disablefullpath)
1422 return (ENODEV);
1423
1424 /* Construct global filesystem path from vp. */
1425 VOP_UNLOCK(vp, 0);

--- 10 unchanged lines hidden (view full) ---

1436 goto out;
1437 }
1438
1439 /*
1440 * Re-lookup the vnode by path to detect a possible rename.
1441 * As a side effect, the vnode is relocked.
1442 * If vnode was renamed, return ENOENT.
1443 */
1473 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1444 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
1474 UIO_SYSSPACE, path, td);
1475 error = namei(&nd);
1476 if (error != 0) {
1477 vrele(vp);
1478 goto out;
1479 }
1445 UIO_SYSSPACE, path, td);
1446 error = namei(&nd);
1447 if (error != 0) {
1448 vrele(vp);
1449 goto out;
1450 }
1480 vfslocked = NDHASGIANT(&nd);
1481 NDFREE(&nd, NDF_ONLY_PNBUF);
1482 vp1 = nd.ni_vp;
1483 vrele(vp);
1484 if (vp1 == vp)
1485 strcpy(path, rpath);
1486 else {
1487 vput(vp1);
1488 error = ENOENT;
1489 }
1451 NDFREE(&nd, NDF_ONLY_PNBUF);
1452 vp1 = nd.ni_vp;
1453 vrele(vp);
1454 if (vp1 == vp)
1455 strcpy(path, rpath);
1456 else {
1457 vput(vp1);
1458 error = ENOENT;
1459 }
1490 VFS_UNLOCK_GIANT(vfslocked);
1491
1492out:
1493 free(fbuf, M_TEMP);
1494 return (error);
1495}
1460
1461out:
1462 free(fbuf, M_TEMP);
1463 return (error);
1464}