Deleted Added
sdiff udiff text old ( 232420 ) new ( 241896 )
full compact
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 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;
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);
1090 vrele(rdir);
1091 vrele(cdir);
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;
1138 int error;
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);
1152 vrele(rdir);
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;
1205 int error;
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();
1214 vrele(*vp);
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();
1229 vrele(dvp);
1230 CACHE_RLOCK();
1231 return (0);
1232 }
1233 SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, 0, 0);
1234
1235 CACHE_RUNLOCK();
1236 vn_lock(*vp, LK_SHARED | LK_RETRY);
1237 error = VOP_VPTOCNP(*vp, &dvp, cred, buf, buflen);
1238 vput(*vp);
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();
1251 vrele(dvp);
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{
1271 int error, slash_prefixed;
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();
1292 vrele(vp);
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();
1302 vrele(vp);
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();
1311 vrele(vp);
1312 vp = vp1;
1313 CACHE_RLOCK();
1314 continue;
1315 }
1316 if (vp->v_type != VDIR) {
1317 CACHE_RUNLOCK();
1318 vrele(vp);
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();
1330 vrele(vp);
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();
1344 vrele(vp);
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();
1354 vrele(vp);
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;
1416 int error;
1417
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 */
1444 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
1445 UIO_SYSSPACE, path, td);
1446 error = namei(&nd);
1447 if (error != 0) {
1448 vrele(vp);
1449 goto out;
1450 }
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 }
1460
1461out:
1462 free(fbuf, M_TEMP);
1463 return (error);
1464}