Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Jul 2010 08:41:28 GMT
From:      Gabor Kovesdan <gabor@repoman.freebsd.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 181452 for review
Message-ID:  <201007250841.o6P8fSio001208@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181452?ac=10

Change 181452 by gabor@gabor_aspire on 2010/07/25 08:39:08

	- Add more test cases to the testsuite and refactor a bit
	- Some code changes, which are necessary for more complicated resource
	  checks
	- Add support for JLIMIT_NOFILE

Affected files ...

.. //depot/projects/soc2010/gabor_jobs/irix_jobs/sys/fs/fdescfs/fdesc_vfsops.c#2 edit
.. //depot/projects/soc2010/gabor_jobs/irix_jobs/sys/kern/kern_fork.c#4 edit
.. //depot/projects/soc2010/gabor_jobs/irix_jobs/sys/kern/kern_jobs.c#5 edit
.. //depot/projects/soc2010/gabor_jobs/irix_jobs/sys/sys/jobs.h#3 edit
.. //depot/projects/soc2010/gabor_jobs/irix_jobs/tools/test/irix_jobs/jobtest.c#3 edit

Differences ...

==== //depot/projects/soc2010/gabor_jobs/irix_jobs/sys/fs/fdescfs/fdesc_vfsops.c#2 (text+ko) ====

@@ -41,6 +41,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/filedesc.h>
+#include <sys/jobs.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
@@ -183,6 +184,7 @@
 	struct thread *td;
 	struct filedesc *fdp;
 	int lim;
+	int jlim_cur_avail;
 	int i;
 	int last;
 	int freefd;
@@ -198,9 +200,10 @@
 	PROC_LOCK(td->td_proc);
 	lim = lim_cur(td->td_proc, RLIMIT_NOFILE);
 	PROC_UNLOCK(td->td_proc);
+	jlim_cur_avail = irix_jobs_cur_avail(td->td_proc->p_ucred->cr_jid, JLIMIT_NOFILE);
 	fdp = td->td_proc->p_fd;
 	FILEDESC_SLOCK(fdp);
-	last = min(fdp->fd_nfiles, lim);
+	last = min(min(fdp->fd_nfiles, lim), (jlim_cur_avail + fdp->fd_nfiles));
 	freefd = 0;
 	for (i = fdp->fd_freefile; i < last; i++)
 		if (fdp->fd_ofiles[i] == NULL)

==== //depot/projects/soc2010/gabor_jobs/irix_jobs/sys/kern/kern_fork.c#4 (text+ko) ====

@@ -114,7 +114,7 @@
 		td->td_retval[0] = p2->p_pid;
 		td->td_retval[1] = 0;
 		if (td->td_proc->p_ucred->cr_jid != 0)
-			irix_jobs_add_proc(td->td_proc->p_ucred->cr_jid, p2->p_pid);
+			irix_jobs_add_proc(td->td_proc->p_ucred->cr_jid, p2);
 	}
 	return (error);
 }

==== //depot/projects/soc2010/gabor_jobs/irix_jobs/sys/kern/kern_jobs.c#5 (text+ko) ====

@@ -29,6 +29,7 @@
 __FBSDID("$FreeBSD");
 
 #include <sys/errno.h>
+#include <sys/filedesc.h>
 #include <sys/jobs.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
@@ -52,7 +53,7 @@
 static jid_t				 min_free_jid = 1;
 
 struct procentry {
-	pid_t				 pid;
+	struct proc			*td_proc;
 	LIST_ENTRY(procentry)		 entries;
 };
 
@@ -124,15 +125,12 @@
 	}
 */
 
-
-	p = td->td_proc;
-
 	/*
 	 * per-job accounting
 	 */
 	jp = jobentry_alloc(uap->rjid);
 	pp = malloc(sizeof(struct procentry), M_IRIX_JOBS, M_NOWAIT | M_ZERO);
-	pp->pid = p->p_pid;
+	pp->td_proc = td->td_proc;
 	LIST_INIT(&jp->proclist);
 	LIST_INSERT_HEAD(&jp->proclist, pp, entries);
 	JOBLIST_WLOCK;
@@ -142,8 +140,8 @@
 	/*
 	 * per-process accounting
 	 */
-	PROC_LOCK(p);
-	p->p_ucred->cr_jid = uap->rjid;
+	PROC_LOCK(td->td_proc);
+	td->td_proc->p_ucred->cr_jid = uap->rjid;
 	PROC_UNLOCK(p);
 
 	/* success, if we have reached here */
@@ -161,20 +159,24 @@
 	LIST_FOREACH_SAFE(jp, &irix_joblist, entries, jtmp) {
 		if (jp->jid == (jid_t)uap->jid) {
 			LIST_FOREACH_SAFE(pp, &jp->proclist, entries, ptmp) {
-				struct kill_args args;
+				struct kill_args kuap;
+
+				printf("killjob traversed pid %d\n", pp->td_proc->p_pid);
 
-				args.pid = pp->pid;
-				args.signum = uap->signal;
-				if (kill((struct thread *)0, &args) == -1) {
+				kuap.pid = pp->td_proc->p_pid;
+				kuap.signum = uap->signal;
+				if (kill(td, &kuap) == -1) {
 					td->td_retval[0] = -1;
 					JOBLIST_WUNLOCK;
 					return (EPERM);
 				}
 				LIST_REMOVE(pp, entries);
+				free(pp, M_IRIX_JOBS);
 			}
-			td->td_retval[0] = 0;
 			LIST_REMOVE(jp, entries);
 			JOBLIST_WUNLOCK;
+			jobentry_free(jp);
+			td->td_retval[0] = 0;
 			return (0);
 		}
 	}
@@ -272,6 +274,92 @@
 	return (ENOJOB);
 }
 
+#define	SUM_UP(jid, res, expr)	do {						\
+				struct procentry *pp;				\
+										\
+				JOBLIST_RLOCK;					\
+				LIST_FOREACH(jp, &irix_joblist, entries) {	\
+					if (jp->jid == jid) {			\
+						LIST_FOREACH(pp, &jp->proclist, \
+						    entries) {			\
+							res += expr;		\
+						}				\
+						JOBLIST_RUNLOCK;		\
+						return (res);			\
+					}					\
+				}						\
+				}						\
+				while (0)
+
+rlim_t
+irix_jobs_getjusage(jid_t jid, int resource)
+{
+	struct jobentry *jp;
+	rlim_t usage;
+
+	usage = 0;
+
+	if ((jid == 0) || (resource >= JLIMIT_NLIMITS))
+		return ((rlim_t)-1);
+
+	switch(resource) {
+	case JLIMIT_DATA:
+//		SUM_UP(jid, usage, (round_page((vm_offset_t)pp->td_proc->
+//		    p_vmspace->vm->vmdaddr) + ctob(pp->td_proc->p_vmspace->
+//		    vm_dsize));
+		break;
+	case JLIMIT_NOFILE:
+		SUM_UP(jid, usage, pp->td_proc->p_fd->fd_nfiles);
+		break;
+	default:
+		JOBLIST_RLOCK;
+		LIST_FOREACH(jp, &irix_joblist, entries) {
+			if (jp->jid == jid) {
+				JOBLIST_RUNLOCK;
+				return (jp->usage[resource]);
+			}
+		}
+		JOBLIST_RUNLOCK;
+		/* no job entry for existing job, cannot happen */
+		return ((rlim_t)-1);
+	}
+
+}
+
+rlim_t
+irix_jobs_get_cur_avail(jid_t jid, int resource)
+{
+	struct jobentry *jp;
+
+	LIST_FOREACH(jp, &irix_joblist, entries) {
+		if (jp->jid == jid) {
+			if (jp->limits[resource].rlim_cur != RLIM_INFINITY)
+				return (jp->limits[resource].rlim_cur -
+				    irix_jobs_getjusage(jid, resource));
+			else
+				return (RLIM_INFINITY);
+		}
+	}
+	return (RLIM_INFINITY);
+}
+
+rlim_t
+irix_jobs_get_max_avail(jid_t jid, int resource)
+{
+	struct jobentry *jp;
+
+	LIST_FOREACH(jp, &irix_joblist, entries) {
+		if (jp->jid == jid) {
+			if (jp->limits[resource].rlim_max != RLIM_INFINITY)
+				return (jp->limits[resource].rlim_max -
+					    irix_jobs_getjusage(jid, resource));
+			else
+				return (RLIM_INFINITY);
+		}
+	}
+	return (RLIM_INFINITY);                         
+}
+
 int
 irix_jobs_alloc(struct proc *p, int resource, rlim_t amount)
 {
@@ -349,7 +437,7 @@
 	LIST_FOREACH_SAFE(jp, &irix_joblist, entries, jtmp) {
 		if (jp->jid == jid) {
 			LIST_FOREACH_SAFE(pp, &jp->proclist, entries, ptmp) {
-				if (pp->pid == pid) {
+				if (pp->td_proc->p_pid == pid) {
 					LIST_REMOVE(pp, entries);
 					free(pp, M_IRIX_JOBS);
 				}
@@ -366,7 +454,7 @@
 }
 
 void
-irix_jobs_add_proc(jid_t jid, pid_t pid)
+irix_jobs_add_proc(jid_t jid, struct proc *p)
 {
 	struct jobentry *jp, *jtmp;
 	struct procentry *pp;
@@ -375,7 +463,7 @@
 	LIST_FOREACH_SAFE(jp, &irix_joblist, entries, jtmp) {
 		if (jp->jid == jid) {
 			pp = malloc(sizeof(struct procentry), M_IRIX_JOBS, M_NOWAIT);
-			pp->pid = pid;
+			pp->td_proc = p;
 			LIST_INSERT_HEAD(&jp->proclist, pp, entries);
 		}
 	}

==== //depot/projects/soc2010/gabor_jobs/irix_jobs/sys/sys/jobs.h#3 (text+ko) ====

@@ -34,10 +34,13 @@
 
 __BEGIN_DECLS
 jid_t			 getjid_by_pid(pid_t pid);
-void			 irix_jobs_add_proc(jid_t jid, pid_t pid);
+void			 irix_jobs_add_proc(jid_t jid, struct proc *p);
 void			 irix_jobs_remove_proc(jid_t jid, pid_t pid);
 int			 irix_jobs_alloc(struct proc *p, int resource, rlim_t amount);
 void			 irix_jobs_free(struct proc *p, int resource, rlim_t amount);
+rlim_t			 irix_jobs_cur_avail(jid_t jid, int resource);
+rlim_t			 irix_jobs_max_avail(jid_t jid, int resource);
+rlim_t			 irix_jobs_getjusage(jid_t jid, int resource);
 __END_DECLS
 
 #endif  /* _KERNEL */

==== //depot/projects/soc2010/gabor_jobs/irix_jobs/tools/test/irix_jobs/jobtest.c#3 (text+ko) ====

@@ -38,26 +38,97 @@
 #include <string.h>
 #include <unistd.h>
 
+#define PARSE_ARG(var, cfunc, mval)	errno = 0;			\
+					var = cfunc(optarg, &ep, 10);	\
+					if (((errno == ERANGE) &&	\
+					     (var == mval)) ||		\
+					     ((errno == EINVAL) &&	\
+					     (var == 0)))		\
+						err(2, NULL);		\
+					else if (ep[0] != '\0') {	\
+						errno = EINVAL;		\
+						err(2, NULL);		\
+					}
+
+#define SET_LIMIT(var, lim)		int ret;			\
+					struct rlimit rlp;		\
+									\
+					rlp.rlim_cur = (rlim_t)var;	\
+					rlp.rlim_max = (rlim_t)var;	\
+									\
+					ret = setjlimit(jid, lim, &rlp);\
+					if (ret == -1) {		\
+						diag_print("setjlimit()"\
+						    "of " #lim		\
+						    " failed:"		\
+						     " %s.\n",		\
+						     strerror(errno));	\
+						return (1);		\
+					} else				\
+						diag_print(#lim " limit"\
+						    " set to %lld.\n",	\
+						    var);		\
+									\
+					ret = getjlimit(jid, lim, &rlp);\
+					if (ret == -1) {		\
+						diag_print("getjlimit()"\
+						    "of " #lim		\
+						    " failed:"		\
+						    "  %s.\n",		\
+						    strerror(errno));	\
+						return (1);		\
+					} else				\
+						diag_print("getjlimit()"\
+						    " for " #lim	\
+						    " returns "		\
+						    "%lld/%lld.\n",	\
+						    rlp.rlim_cur,	\
+						    rlp.rlim_max);
+
 struct option long_options[] =
 {
-	{"diag",		no_argument,		NULL,	'd'},
+	{"cpu",			required_argument,	NULL,	'c'},
+	{"jlimit-cpu",		required_argument,	NULL,	'C'},
+	{"data",		required_argument,	NULL,	'd'},
+	{"jlimit-data",		required_argument,	NULL,	'D'},
 	{"exec",		required_argument,	NULL,	'e'},
-	{"fork",		optional_argument,	NULL,	'f'},
-	{"jlimit_numproc",	required_argument,	NULL,	'n'},
+	{"stat",		required_argument,	NULL,	'f'},
+	{"jlimit-fileno",	required_argument,	NULL,	'F'},
 	{"job",			no_argument,		NULL,	'j'},
 	{"killjob",		no_argument,		NULL,	'k'},
+	{"mem",			required_argument,	NULL,	'm'},
+	{"jlimit-pmem",		required_argument,	NULL,	'M'},
+	{"proc",		optional_argument,	NULL,	'p'},
+	{"jlimit-numproc",	required_argument,	NULL,	'P'},
+	{"resident",		required_argument,	NULL,	'r'},
+	{"jlimit-rss",		required_argument,	NULL,	'R'},
 	{"shell",		no_argument,		NULL,	's'},
+	{"vmem",		required_argument,	NULL,	'v'},
+	{"jlimit-vmem",		required_argument,	NULL,	'V'},
+	{"verbose",		no_argument,		NULL,	'x'},
 	{NULL,			no_argument,		NULL,	0}
 };
 
-static const char		*optstr = "de:f:jkn:s";
+static const char		*optstr = "c:C:d:D:e:f:F:jkm:M:p:P:r:R:sv:V:x";
 
+static unsigned long long	 cflag;
+static long long		 Cflag;
+static unsigned long long	 dflag;
+static long long		 Dflag;
 static char			*eflag;
 static unsigned long long	 fflag;
+static long long		 Fflag;
 static bool			 jflag;
 static bool			 kflag;
-static long long		 nflag;
+static unsigned long long	 mflag;
+static long long		 Mflag;
+static unsigned long long	 pflag;
+static long long		 Pflag;
+static unsigned long long	 rflag;
+static long long		 Rflag;
 static bool			 sflag;
+static unsigned long long	 vflag;
+static long long		 Vflag;
 
 static int	null_print(const char * restrict, ...);
 static int	(*diag_print)(const char * restrict format, ...) = null_print;
@@ -89,22 +160,26 @@
 	while (((c = getopt_long(argc, argv, optstr, long_options, NULL)) !=
 	    -1)) {
 		switch (c) {
+		case 'c':
+			PARSE_ARG(cflag, strtoull, ULLONG_MAX);
+			break;
+		case 'C':
+			PARSE_ARG(Cflag, strtoll, LLONG_MAX);
+			break;
 		case 'd':
-			diag_print = printf;
+			PARSE_ARG(dflag, strtoull, ULLONG_MAX);
+			break;
+		case 'D':
+			PARSE_ARG(Dflag, strtoll, LLONG_MAX);
 			break;
 		case 'e':
 			eflag = strdup(optarg);
 			break;
 		case 'f':
-			errno = 0;
-			fflag = strtoull(optarg, &ep, 10);
-			if (((errno == ERANGE) && (fflag == ULLONG_MAX)) ||
-			    ((errno == EINVAL) && (fflag == 0)))
-				err(2, NULL);
-			else if (ep[0] != '\0') {
-				errno = EINVAL;
-				err(2, NULL);
-			}
+			PARSE_ARG(fflag, strtoull, ULLONG_MAX);
+			break;
+		case 'F':
+			PARSE_ARG(Fflag, strtoll, LLONG_MAX);
 			break;
 		case 'j':
 			jflag = true;
@@ -112,26 +187,42 @@
 		case 'k':
 			kflag = true;
 			break;
-		case 'n':
-			errno = 0;
-			nflag = strtoll(optarg, &ep, 10);
-			if (((errno == ERANGE) && (nflag == LLONG_MAX)) ||
-			     ((errno == EINVAL) && (nflag == 0)))
-				err(2, NULL);
-			else if (ep[0] != '\0') {
-				errno = EINVAL;
-				err(2, NULL);
-			}
+		case 'm':
+			PARSE_ARG(mflag, strtoull, ULLONG_MAX);
+			break;
+		case 'M':
+			PARSE_ARG(Mflag, strtoll, LLONG_MAX);
+			break;
+		case 'p':
+			PARSE_ARG(pflag, strtoull, ULLONG_MAX);
+			break;
+		case 'P':
+			PARSE_ARG(Pflag, strtoll, LLONG_MAX);
+			break;
+		case 'r':
+			PARSE_ARG(rflag, strtoull, ULLONG_MAX);
+			break;
+		case 'R':
+			PARSE_ARG(Pflag, strtoll, LLONG_MAX);
 			break;
 		case 's':
 			sflag = true;
 			break;
+		case 'v':
+			PARSE_ARG(vflag, strtoull, ULLONG_MAX);
+			break;
+		case 'V':
+			PARSE_ARG(Vflag, strtoll, LLONG_MAX);
+			break;
+		case 'x':
+			diag_print = printf;
+			break;
 		default:
 			usage();
 		}
 	}
 
-	if (sflag && fflag)
+	if (sflag && pflag)
 		usage();
 
 	if (jflag) {
@@ -152,40 +243,64 @@
 			return (1);
 	}
 
-	if (nflag > 0) {
-		int ret;
-		struct rlimit rlp;
+	/*
+	 * Setting resource limits on creaated job.
+	 */
+
+	if (Cflag > 0) {
+		SET_LIMIT(Cflag, JLIMIT_CPU);
+	}
+
+        if (Dflag > 0) {
+		SET_LIMIT(Fflag, JLIMIT_DATA);
+	}
+
+	if (Fflag > 0) {
+		SET_LIMIT(Fflag, JLIMIT_NOFILE);
+	}
+
+	if (Mflag > 0) {
+		SET_LIMIT(Mflag, JLIMIT_PMEM);
+	}
+
+	if (Pflag > 0) {
+		SET_LIMIT(Pflag, JLIMIT_NUMPROC);
+	}
 
-		rlp.rlim_cur = (rlim_t)nflag;
-		rlp.rlim_max = (rlim_t)nflag;
+	if (Rflag > 0) {
+		SET_LIMIT(Fflag, JLIMIT_RSS);
+	}
 
-		ret = setjlimit(jid, JLIMIT_NUMPROC, &rlp);
+	if (Vflag > 0) {
+		SET_LIMIT(Fflag, JLIMIT_VMEM);
+	}
 
-		if (ret == -1) {
-			diag_print("setjlimit() failed: %s.\n",
-				strerror(errno));
-			return (1);
-		} else
-			diag_print("JLIMIT_NUMPROC limit set to %lld.\n",
-			    nflag);
+	/*
+	 * Start resource consumption.
+	 */
 
-		ret = getjlimit(jid, JLIMIT_NUMPROC, &rlp);
+	if (cflag > 0) {
+		/* XXX */
+	}
 
-		if (ret == -1) {
-			diag_print("getjlimit() failed: %s.\n",
-				strerror(errno));
-			return (1);
-		} else
-			diag_print("getjlimit() says JLIMIT_NUMPROC limit is"
-			    "set to %lld/%lld.\n", rlp.rlim_cur, rlp.rlim_max);
+	if (dflag > 0) {
+		/* XXX */
 	}
 
 	if (fflag > 0) {
-		for (unsigned long long i = 0; i < fflag; i++) {
+		/* XXX */
+	}
+
+	if (mflag > 0) {
+		/* XXX */
+	}
+
+	if (pflag > 0) {
+		for (unsigned long long i = 0; i < pflag; i++) {
 			pid = fork();
 			if (pid == 0) {
-				diag_print("Forked process' getjid() returns: %d.\n",
-				    (int)getjid());
+				diag_print("Forked process' getjid()"
+				     " returns: %d.\n", (int)getjid());
 				sleep(5);
 				exit(EXIT_SUCCESS);
 			} else if (pid == -1) {
@@ -197,6 +312,18 @@
 		}
 	}
 
+	if (rflag > 0) {
+		/* XXX */
+	}
+
+	if (vflag > 0) {
+		/* XXX */
+	}
+
+	/*
+	 * Misc debug and testing features.
+	 */
+
 	if (sflag) {
 		char *eargv[2];
 
@@ -210,8 +337,9 @@
 	if (kflag && (pid != 0)) {
 		int ret;
 
-		diag_print("Let's suicide, sending SIGINT to processes of jid %lld...\n", getjid());
-		ret = killjob(getjid(), SIGINT);
+		diag_print("Let's suicide, sending SIGINT to processes of"
+		    " jid %lld...\n", jid);
+		ret = killjob(jid, SIGINT);
 		if (ret == -1) {
 			diag_print("killjob() failed: %s.\n",
 			    strerror(errno));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007250841.o6P8fSio001208>