DragonFly kernel List (threaded) for 2009-07
DragonFly BSD
DragonFly kernel List (threaded) for 2009-07
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

factoring out "at" syscalls common code in nlookup


From: Nicolas Thery <nthery@xxxxxxxxx>
Date: Sun, 26 Jul 2009 21:46:31 +0200

Hello,

As part of implementing the at family of syscalls (openat(),
fstatat(), ...), I propose to put the common code handling the file
descriptor argument in the namecache as shown in the patch below.

Any objection?

Cheers,
Nicolas

---
 sys/kern/vfs_nlookup.c  |   48 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/kern/vfs_syscalls.c |   32 +++---------------------------
 sys/sys/nlookup.h       |    3 ++
 3 files changed, 55 insertions(+), 28 deletions(-)

diff --git a/sys/kern/vfs_nlookup.c b/sys/kern/vfs_nlookup.c
index 09758a6..4e1552a 100644
--- a/sys/kern/vfs_nlookup.c
+++ b/sys/kern/vfs_nlookup.c
@@ -65,6 +65,7 @@
 #include <sys/malloc.h>
 #include <sys/stat.h>
 #include <sys/objcache.h>
+#include <sys/file.h>

 #ifdef KTRACE
 #include <sys/ktrace.h>
@@ -128,6 +129,49 @@ nlookup_init(struct nlookupdata *nd,
     return(error);
 }

+
+/*
+ * nlookup_init() for "at" family of syscalls.
+ *
+ * Works similarly to nlookup_init() but if path is relative and fd is not
+ * AT_FDCWD, path is interpreted relative to the directory pointed to by fd.
+ *
+ * Takes a ref on the file entry pointed to by fd that will be dropped by
+ * nlookup_done().
+ */
+int
+nlookup_init_at(struct nlookupdata *nd, int fd, const char *path,
+		enum uio_seg seg, int flags)
+{
+	struct thread *td = curthread;
+	struct proc *p = td->td_proc;
+	struct file* fp;
+	struct vnode *vp;
+	int error;
+
+	if  ((error = nlookup_init(nd, path, seg, flags)) != 0)
+		return (error);
+
+	if (nd->nl_path[0] != '/' && fd != AT_FDCWD) {
+		if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
+			goto done;
+		nd->nl_atfp = fp;
+		vp = (struct vnode*)fp->f_data;
+		if (vp->v_type != VDIR || fp->f_nchandle.ncp == NULL) {
+			error = ENOTDIR;
+			goto done;
+		}
+		cache_drop(&nd->nl_nch);
+		cache_copy(&fp->f_nchandle, &nd->nl_nch);
+	}
+
+done:
+	if (error)
+		nlookup_done(nd);
+	return (error);
+
+}
+
 /*
  * This works similarly to nlookup_init() but does not assume a process
  * context.  rootnch is always chosen for the root directory and the cred
@@ -229,6 +273,10 @@ nlookup_done(struct nlookupdata *nd)
 	vrele(nd->nl_dvp);
 	nd->nl_dvp = NULL;
     }
+    if (nd->nl_atfp) {
+	    fdrop(nd->nl_atfp);
+	    nd->nl_atfp = NULL;
+    }
     nd->nl_flags = 0;	/* clear remaining flags (just clear everything) */
 }

diff --git a/sys/sys/nlookup.h b/sys/sys/nlookup.h
index cec3b96..cc709cc 100644
--- a/sys/sys/nlookup.h
+++ b/sys/sys/nlookup.h
@@ -85,6 +85,8 @@ struct nlookupdata {
 	int		nl_flags;	/* operations flags */
 	int		nl_loopcnt;	/* symlinks encountered */

+	struct file	*nl_atfp;	/* refs nlookup_init_at() fd or NULL */
+
 	/*
 	 * These fields are populated by vn_open().  nlookup_done() will
 	 * vn_close() a non-NULL vp so if you extract it be sure to NULL out
@@ -144,6 +146,7 @@ struct nlookupdata {
 #ifdef _KERNEL

 int nlookup_init(struct nlookupdata *, const char *, enum uio_seg, int);
+int nlookup_init_at(struct nlookupdata *, int, const char *, enum
uio_seg, int);
 int nlookup_init_raw(struct nlookupdata *, const char *, enum
uio_seg, int, struct ucred *, struct nchandle *);
 void nlookup_set_cred(struct nlookupdata *nd, struct ucred *cred);
 void nlookup_zero(struct nlookupdata *);
-- 
1.6.0



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]