svn commit: r256993 - in projects/vps/sys: fs/vpsfs kern sys vps
Will Andrews
will at FreeBSD.org
Wed Oct 23 17:18:55 UTC 2013
Author: will
Date: Wed Oct 23 17:18:53 2013
New Revision: 256993
URL: http://svnweb.freebsd.org/changeset/base/256993
Log:
Sync with svn.7he.at/vps/trunk r194.
r194 | klaus | 2013-07-26 13:49:49 -0600 (Fri, 26 Jul 2013) | 4 lines
Added a failsafe vn_fullpath1() version, that still needs a little
bit of work.
Submitted by: Klaus P. Ohrhallinger <k at 7he.at>
Modified:
projects/vps/sys/fs/vpsfs/vpsfs_quota.c
projects/vps/sys/kern/vfs_cache.c
projects/vps/sys/kern/vfs_default.c
projects/vps/sys/sys/vnode.h
projects/vps/sys/vps/vps_snapst.c
projects/vps/sys/vps/vps_suspend.c
Modified: projects/vps/sys/fs/vpsfs/vpsfs_quota.c
==============================================================================
--- projects/vps/sys/fs/vpsfs/vpsfs_quota.c Wed Oct 23 17:17:57 2013 (r256992)
+++ projects/vps/sys/fs/vpsfs/vpsfs_quota.c Wed Oct 23 17:18:53 2013 (r256993)
@@ -67,10 +67,6 @@ static int vpsfs_readdir(struct thread *
int dirbuflen, struct vpsfs_limits *,
void (*cbfunc)(struct vnode *, struct vpsfs_limits *, struct thread *));
-static int get_next_dirent(struct vnode *vp, struct dirent **dpp,
- char *dirbuf, int dirbuflen, off_t *off, char **cpos, int *len,
- int *eofflag, struct thread *td);
-
static void vpsfs_calcvnode(struct vnode *vp, struct vpsfs_limits *limits,
struct thread *td);
@@ -610,63 +606,6 @@ vpsfs_readdir(struct thread *td, struct
return (error);
}
-/* copied from kern/vfs_default.c */
-static int
-get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf,
- int dirbuflen, off_t *off, char **cpos, int *len,
- int *eofflag, struct thread *td)
-{
- int error, reclen;
- struct uio uio;
- struct iovec iov;
- struct dirent *dp;
-
- KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp));
- KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp));
-
- if (*len == 0) {
- iov.iov_base = dirbuf;
- iov.iov_len = dirbuflen;
-
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = *off;
- uio.uio_resid = dirbuflen;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_READ;
- uio.uio_td = td;
-
- *eofflag = 0;
-
-#ifdef MAC
- error = mac_vnode_check_readdir(td->td_ucred, vp);
- if (error == 0)
-#endif
- error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag,
- NULL, NULL);
- if (error)
- return (error);
-
- *off = uio.uio_offset;
-
- *cpos = dirbuf;
- *len = (dirbuflen - uio.uio_resid);
- }
-
- dp = (struct dirent *)(*cpos);
- reclen = dp->d_reclen;
- *dpp = dp;
-
- /* check for malformed directory.. */
- if (reclen < DIRENT_MINSIZE)
- return (EINVAL);
-
- *cpos += reclen;
- *len -= reclen;
-
- return (0);
-}
-
#endif /* VPS */
/* EOF */
Modified: projects/vps/sys/kern/vfs_cache.c
==============================================================================
--- projects/vps/sys/kern/vfs_cache.c Wed Oct 23 17:17:57 2013 (r256992)
+++ projects/vps/sys/kern/vfs_cache.c Wed Oct 23 17:18:53 2013 (r256993)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/dirent.h>
#include <sys/filedesc.h>
#include <sys/fnv_hash.h>
#include <sys/kernel.h>
@@ -309,13 +310,8 @@ SYSCTL_OPAQUE(_vfs_cache, OID_AUTO, nchs
static void cache_zap(struct namecache *ncp);
static int vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, char *buf,
u_int *buflen);
-#ifdef VPS
-int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
- char *buf, char **retbuf, u_int buflen);
-#else
static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
char *buf, char **retbuf, u_int buflen);
-#endif
static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries");
@@ -1269,11 +1265,7 @@ vn_vptocnp_locked(struct vnode **vp, str
/*
* The magic behind kern___getcwd() and vn_fullpath().
*/
-#ifdef VPS
-int
-#else
static int
-#endif
vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
char *buf, char **retbuf, u_int buflen)
{
@@ -1368,6 +1360,357 @@ vn_fullpath1(struct thread *td, struct v
return (0);
}
+
+/* ----------------------------------------------------------- */
+
+/*
+ XXX lookup for /dev/console doesn't work, altough td->td_vps and
+ td->td_ucred->cr_vps are right.
+ XXX for this failure no error is returned
+ XXX limit recursion depth !!!
+ */
+
+/*
+ * Search a directory for a given inode number, recursing into
+ * subdirectories.
+ */
+static int
+vn_fullpath1_findparentdir_recurse(struct vnode *dvp, struct ucred *cred,
+ int inodenum, struct vnode **retvp)
+{
+ struct componentname cnp;
+ struct dirent *dp;
+ struct vnode *vp;
+ char *dirbuf;
+ char *cpos;
+ off_t off;
+ int dirbuflen;
+ int eofflag;
+ int error;
+ int len;
+
+ dirbuflen = PATH_MAX;
+ dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
+
+ cpos = NULL;
+ off = 0;
+ len = 0;
+
+ do {
+ error = get_next_dirent(dvp, &dp, dirbuf, dirbuflen,
+ &off, &cpos, &len, &eofflag, curthread);
+ if (error != 0)
+ goto out;
+
+ if (!strcmp(dp->d_name, ".") ||
+ !strcmp(dp->d_name, "..") ||
+ dp->d_fileno == 0)
+ continue;
+
+ cnp.cn_pnbuf = NULL;
+ cnp.cn_consume = 0;
+ cnp.cn_nameptr = dp->d_name;
+ cnp.cn_namelen = strlen(dp->d_name);
+ cnp.cn_lkflags = LK_SHARED | LK_RETRY;
+ cnp.cn_thread = curthread;
+ cnp.cn_cred = cred;
+ error = VOP_LOOKUP(dvp, &vp, &cnp);
+ if (error != 0)
+ goto out;
+
+ if (dp->d_fileno == inodenum) {
+ *retvp = dvp;
+ vunref(vp);
+ VOP_UNLOCK(vp, 0);
+ error = 0;
+ goto out;
+ }
+
+ if (vp->v_type == VDIR) {
+ error = vn_fullpath1_findparentdir_recurse(vp, cred,
+ inodenum, retvp);
+ if (error != ENOENT) {
+ vunref(vp);
+ VOP_UNLOCK(vp, 0);
+ error = 0;
+ goto out;
+ }
+ }
+
+ vunref(vp);
+ VOP_UNLOCK(vp, 0);
+
+ } while (len > 0 || !eofflag);
+
+ error = ENOENT;
+
+ out:
+ free(dirbuf, M_TEMP);
+
+ return (error);
+}
+
+/*
+ * Search through the filesystem that owns 'vp' for (one of) its
+ * parent directories.
+ */
+static int
+vn_fullpath1_findparentdir(struct vnode *vp, struct ucred *cred,
+ struct vnode **outvp)
+{
+ struct vattr vattr;
+ struct vnode *rootvp;
+ struct vnode *dvp;
+ int error;
+
+ if (VOP_ISLOCKED(vp) == 0)
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+
+ /* Get inode number of file. */
+ error = VOP_GETATTR(vp, &vattr, cred);
+ VOP_UNLOCK(vp, 0);
+ if (error != 0)
+ return (error);
+
+ error = VFS_ROOT(vp->v_mount, LK_EXCLUSIVE | LK_RETRY, &rootvp);
+ if (error != 0)
+ return (error);
+
+ error = vn_fullpath1_findparentdir_recurse(rootvp, cred,
+ vattr.va_fileid, &dvp);
+ if (error == 0)
+ *outvp = dvp;
+
+ vunref(rootvp);
+ VOP_UNLOCK(rootvp, 0);
+
+ return (error);
+}
+
+static int
+vn_fullpath1_fallback(struct thread *td, struct vnode *vp,
+ struct vnode *rdir, char *buf, char **retbuf, u_int buflen)
+{
+ struct componentname cnp;
+ struct vattr vattr;
+ struct vnode *dvp2;
+ struct vnode *dvp;
+ struct dirent *dp;
+ char *dirbuf;
+ char *cpos;
+ off_t off;
+ int dirbuflen;
+ int inodenum;
+ int eofflag;
+ int error;
+ int len;
+
+ dirbuflen = PATH_MAX;
+ dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
+
+ buflen -= 1;
+ buf[buflen] = 0;
+
+ if (vp->v_type == VDIR) {
+ dvp = vp;
+
+ if (VOP_ISLOCKED(dvp) == 0)
+ vn_lock(dvp, LK_SHARED | LK_RETRY);
+
+ } else {
+ char buf2[MAXPATHLEN];
+ int buflen2;
+
+ /* Get the parent directory. */
+
+ buflen2 = sizeof(buf2);
+ memset(buf2, 0, sizeof(buf2));
+
+ /*
+ * Since this step is the most expensive one,
+ * try the namecache for this one.
+ */
+ vref(vp);
+ CACHE_RLOCK();
+ error = vn_vptocnp_locked(&vp, td->td_ucred, buf2, &buflen2);
+ if (error == 0)
+ CACHE_RUNLOCK();
+ vrele(vp);
+ dvp = vp;
+ /*
+ // debugging
+ dvp = NULL;
+ error = ENOENT;
+ */
+
+ if (error == 0) {
+ buflen -= sizeof(buf2)-buflen2;
+ memcpy(buf+buflen, buf2+buflen2, sizeof(buf2)-buflen2);
+
+ } else {
+ /* Do it the *expensive* way. */
+
+ printf("%s: WARNING: looking up by "
+ "vn_fullpath1_findparentdir(vp=%p, ...)\n",
+ __func__, vp);
+ error = vn_fullpath1_findparentdir(vp, td->td_ucred, &dvp);
+ if (error != 0)
+ goto out;
+
+ vn_lock(dvp, LK_SHARED | LK_RETRY);
+
+ /* Get inode number of file. */
+ if (VOP_ISLOCKED(vp) == 0)
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ error = VOP_GETATTR(vp, &vattr, td->td_ucred);
+ VOP_UNLOCK(vp, 0);
+ if (error != 0) {
+ VOP_UNLOCK(dvp, 0);
+ goto out;
+ }
+ inodenum = vattr.va_fileid;
+
+ /* Now we know the parent directory so search it for the file. */
+ cpos = NULL;
+ off = 0;
+ len = 0;
+ error = ENOENT;
+
+ do {
+ error = get_next_dirent(dvp, &dp, dirbuf, dirbuflen,
+ &off, &cpos, &len, &eofflag, td);
+ if (error != 0) {
+ VOP_UNLOCK(dvp, 0);
+ goto out;
+ }
+
+ if (dp->d_fileno == inodenum) {
+ /* Found it ! */
+ if (buflen < strlen(dp->d_name)) {
+ error = ENOMEM;
+ VOP_UNLOCK(dvp, 0);
+ goto out;
+ }
+ buflen -= strlen(dp->d_name);
+ memcpy(buf+buflen, dp->d_name, strlen(dp->d_name));
+ error = 0;
+ break;
+ }
+ error = ENOENT;
+ } while (len > 0 || !eofflag);
+
+ if (error != 0) {
+ printf("%s: line %d\n", __func__, __LINE__);
+ VOP_UNLOCK(dvp, 0);
+ goto out;
+ }
+ }
+
+ }
+
+ for (;;) {
+
+ /* Separate component names with '/'. */
+ if (buflen < 1) {
+ error = ENOMEM;
+ VOP_UNLOCK(dvp, 0);
+ goto out;
+ }
+ buflen -= 1;
+ memcpy(buf+buflen, "/", 1);
+ *retbuf = buf+buflen;
+
+ if (dvp == rdir) {
+ /* Reached (relative) root directory. */
+ VOP_UNLOCK(dvp, 0);
+ break;
+ }
+
+ if (dvp->v_vflag & VV_ROOT) {
+ /* Crossing filesystems. */
+ dvp2 = dvp->v_mount->mnt_vnodecovered;
+ VOP_UNLOCK(dvp, 0);
+ vn_lock(dvp2, LK_SHARED | LK_RETRY);
+ dvp = dvp2;
+ }
+
+ /* Get inode number of directory. */
+ error = VOP_GETATTR(dvp, &vattr, td->td_ucred);
+ if (error != 0) {
+ VOP_UNLOCK(dvp, 0);
+ goto out;
+ }
+ inodenum = vattr.va_fileid;
+
+ /* Lookup "..". */
+ cnp.cn_pnbuf = NULL;
+ cnp.cn_consume = 0;
+ cnp.cn_nameptr = "..";
+ cnp.cn_namelen = 2;
+ cnp.cn_lkflags = LK_SHARED;
+ cnp.cn_thread = curthread;
+ cnp.cn_cred = td->td_ucred;
+ error = VOP_LOOKUP(dvp, &dvp2, &cnp);
+ if (error != 0) {
+ VOP_UNLOCK(dvp, 0);
+ goto out;
+ }
+
+ vunref(dvp2);
+ VOP_UNLOCK(dvp, 0);
+ dvp = dvp2;
+
+ cpos = NULL;
+ off = 0;
+ len = 0;
+ error = ENOENT;
+
+ do {
+ error = get_next_dirent(dvp2, &dp, dirbuf, dirbuflen,
+ &off, &cpos, &len, &eofflag, td);
+ if (error != 0) {
+ VOP_UNLOCK(dvp2, 0);
+ goto out;
+ }
+
+ if (dp->d_fileno == inodenum) {
+ /* Found it ! */
+ if (buflen < strlen(dp->d_name)) {
+ error = ENOMEM;
+ VOP_UNLOCK(dvp2, 0);
+ goto out;
+ }
+ buflen -= strlen(dp->d_name);
+ memcpy(buf+buflen, dp->d_name, strlen(dp->d_name));
+ break;
+ }
+ error = ENOENT;
+ } while (len > 0 || !eofflag);
+ }
+
+ out:
+ free(dirbuf, M_TEMP);
+
+ return (error);
+}
+
+int
+vn_fullpath1_failsafe(struct thread *td, struct vnode *vp,
+ struct vnode *rdir, char *buf, char **retbuf, u_int buflen)
+{
+ int error;
+
+ error = vn_fullpath1(td, vp, rdir, buf, retbuf, buflen);
+ if (error != ENOENT)
+ return (error);
+
+ error = vn_fullpath1_fallback(td, vp, rdir, buf, retbuf, buflen);
+
+ return (error);
+}
+
+/* ----------------------------------------------------------- */
+
struct vnode *
vn_dir_dd_ino(struct vnode *vp)
{
Modified: projects/vps/sys/kern/vfs_default.c
==============================================================================
--- projects/vps/sys/kern/vfs_default.c Wed Oct 23 17:17:57 2013 (r256992)
+++ projects/vps/sys/kern/vfs_default.c Wed Oct 23 17:18:53 2013 (r256993)
@@ -69,10 +69,6 @@ __FBSDID("$FreeBSD$");
static int vop_nolookup(struct vop_lookup_args *);
static int vop_norename(struct vop_rename_args *);
static int vop_nostrategy(struct vop_strategy_args *);
-static int get_next_dirent(struct vnode *vp, struct dirent **dpp,
- char *dirbuf, int dirbuflen, off_t *off,
- char **cpos, int *len, int *eofflag,
- struct thread *td);
static int dirent_exists(struct vnode *vp, const char *dirname,
struct thread *td);
@@ -261,7 +257,7 @@ vop_nostrategy (struct vop_strategy_args
return (EOPNOTSUPP);
}
-static int
+int
get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf,
int dirbuflen, off_t *off, char **cpos, int *len,
int *eofflag, struct thread *td)
Modified: projects/vps/sys/sys/vnode.h
==============================================================================
--- projects/vps/sys/sys/vnode.h Wed Oct 23 17:17:57 2013 (r256992)
+++ projects/vps/sys/sys/vnode.h Wed Oct 23 17:18:53 2013 (r256993)
@@ -577,6 +577,7 @@ vn_canvmio(struct vnode *vp)
* Public vnode manipulation functions.
*/
struct componentname;
+struct dirent;
struct file;
struct mount;
struct nameidata;
@@ -609,6 +610,10 @@ int getnewvnode(const char *tag, struct
struct vnode **vpp);
void getnewvnode_reserve(u_int count);
void getnewvnode_drop_reserve(void);
+int get_next_dirent(struct vnode *vp, struct dirent **dpp,
+ char *dirbuf, int dirbuflen, off_t *off,
+ char **cpos, int *len, int *eofflag,
+ struct thread *td);
int insmntque1(struct vnode *vp, struct mount *mp,
void (*dtr)(struct vnode *, void *), void *dtr_arg);
int insmntque(struct vnode *vp, struct mount *mp);
@@ -659,6 +664,8 @@ int vn_close(struct vnode *vp,
int flags, struct ucred *file_cred, struct thread *td);
void vn_finished_write(struct mount *mp);
void vn_finished_secondary_write(struct mount *mp);
+int vn_fullpath1_failsafe(struct thread *td, struct vnode *vp,
+ struct vnode *rdir, char *buf, char **retbuf, u_int buflen);
int vn_isdisk(struct vnode *vp, int *errp);
int _vn_lock(struct vnode *vp, int flags, char *file, int line);
#define vn_lock(vp, flags) _vn_lock(vp, flags, __FILE__, __LINE__)
Modified: projects/vps/sys/vps/vps_snapst.c
==============================================================================
--- projects/vps/sys/vps/vps_snapst.c Wed Oct 23 17:17:57 2013 (r256992)
+++ projects/vps/sys/vps/vps_snapst.c Wed Oct 23 17:18:53 2013 (r256993)
@@ -656,6 +656,11 @@ vps_snapshot_vnodepath(struct vps_snapst
{
struct vps_dumpobj *o1;
struct vps_dump_filepath *vdfp;
+ /*
+ struct ucred *save_ucred;
+ struct vps *save_vps;
+ struct thread *td;
+ */
char *retbuf, *buf;
int error;
@@ -671,9 +676,29 @@ vps_snapshot_vnodepath(struct vps_snapst
vrele(vp);
return (ENOMEM);
}
+
+#if 0
+// not yet ... for devfs lookups
+ td = curthread;
+ save_ucred = td->td_ucred;
+ save_vps = td->td_vps;
+ td->td_ucred = crdup(save_ucred);
+ vps_deref(td->td_ucred->cr_vps, td->td_ucred);
+ td->td_ucred->cr_vps = vps;
+ vps_ref(td->td_ucred->cr_vps, td->td_ucred);
+ td->td_vps = vps;
+#endif
+
retbuf = "-";
- error = vn_fullpath1(curthread, vp, vps->_rootvnode,
+ error = vn_fullpath1_failsafe(curthread, vp, vps->_rootvnode,
buf, &retbuf, MAXPATHLEN);
+
+#if 0
+ crfree(td->td_ucred);
+ td->td_ucred = save_ucred;
+ td->td_vps = save_vps;
+#endif
+
if (error != 0) {
free(buf, M_TEMP);
vrele(vp);
Modified: projects/vps/sys/vps/vps_suspend.c
==============================================================================
--- projects/vps/sys/vps/vps_suspend.c Wed Oct 23 17:17:57 2013 (r256992)
+++ projects/vps/sys/vps/vps_suspend.c Wed Oct 23 17:18:53 2013 (r256993)
@@ -118,9 +118,6 @@ static int vps_access_vmspace(struct vms
size_t len, void *buf, int prot);
static int vps_resume_relinkvnodes(struct vps *vps);
-static int get_next_dirent(struct vnode *vp, struct dirent **dpp,
- char *dirbuf, int dirbuflen, off_t *off, char **cpos,
- int *len, int *eofflag, struct thread *td);
static int vps_suspend_relink_delete(struct vnode *vp);
static int vps_suspend_mod_refcnt;
@@ -981,65 +978,6 @@ vps_suspend_relink_delete(struct vnode *
return (error);
}
-#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4)
-
-/* copied from kern/vfs_default.c */
-static int
-get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf,
- int dirbuflen, off_t *off, char **cpos, int *len,
- int *eofflag, struct thread *td)
-{
- int error, reclen;
- struct uio uio;
- struct iovec iov;
- struct dirent *dp;
-
- KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp));
- KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp));
-
- if (*len == 0) {
- iov.iov_base = dirbuf;
- iov.iov_len = dirbuflen;
-
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = *off;
- uio.uio_resid = dirbuflen;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_READ;
- uio.uio_td = td;
-
- *eofflag = 0;
-
-#ifdef MAC
- error = mac_vnode_check_readdir(td->td_ucred, vp);
- if (error == 0)
-#endif
- error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag,
- NULL, NULL);
- if (error)
- return (error);
-
- *off = uio.uio_offset;
-
- *cpos = dirbuf;
- *len = (dirbuflen - uio.uio_resid);
- }
-
- dp = (struct dirent *)(*cpos);
- reclen = dp->d_reclen;
- *dpp = dp;
-
- /* check for malformed directory.. */
- if (reclen < DIRENT_MINSIZE)
- return (EINVAL);
-
- *cpos += reclen;
- *len -= reclen;
-
- return (0);
-}
-
static int
vps_suspend_modevent(module_t mod, int type, void *data)
{
More information about the svn-src-projects
mailing list