PERFORCE change 181452 for review
Gabor Kovesdan
gabor at repoman.freebsd.org
Sun Jul 25 08:41:30 UTC 2010
http://p4web.freebsd.org/@@181452?ac=10
Change 181452 by gabor at 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));
More information about the p4-projects
mailing list