Whamcloud - gitweb
LU-17744 ldiskfs: mballoc stats fixes
[fs/lustre-release.git] / lustre / obdclass / jobid.c
index 1093f78..1767c17 100644 (file)
@@ -60,7 +60,7 @@ struct jobid_pid_map {
        spinlock_t              jp_lock; /* protects jp_jobid */
        char                    jp_jobid[LUSTRE_JOBID_SIZE];
        unsigned int            jp_joblen;
-       atomic_t                jp_refcount;
+       struct kref             jp_refcount;
        pid_t                   jp_pid;
 };
 
@@ -182,6 +182,11 @@ static void jobid_prune(struct work_struct *work)
        rhashtable_walk_enter(&session_jobids, &iter);
        rhashtable_walk_start(&iter);
        while ((sj = rhashtable_walk_next(&iter)) != NULL) {
+               if (IS_ERR(sj)) {
+                       if (PTR_ERR(sj) == -EAGAIN)
+                               continue;
+                       break;
+               }
                if (!hlist_empty(&sj->sj_session->tasks[PIDTYPE_SID])) {
                        remaining++;
                        continue;
@@ -217,7 +222,7 @@ static int cfs_access_process_vm(struct task_struct *tsk,
        /* Just copied from kernel for the kernels which doesn't
         * have access_process_vm() exported
         */
-       struct vm_area_struct *vma;
+       struct vm_area_struct *vma = NULL;
        struct page *page;
        void *old_buf = buf;
 
@@ -234,7 +239,11 @@ static int cfs_access_process_vm(struct task_struct *tsk,
                int bytes, rc, offset;
                void *maddr;
 
-#if defined(HAVE_GET_USER_PAGES_GUP_FLAGS)
+#if defined(HAVE_GET_USER_PAGES_WITHOUT_VMA)
+               rc = get_user_pages(addr, 1, write ? FOLL_WRITE : 0, &page);
+               if (rc > 0)
+                       vma = vma_lookup(mm, addr);
+#elif defined(HAVE_GET_USER_PAGES_GUP_FLAGS)
                rc = get_user_pages(addr, 1, write ? FOLL_WRITE : 0, &page,
                                    &vma);
 #elif defined(HAVE_GET_USER_PAGES_6ARG)
@@ -242,7 +251,7 @@ static int cfs_access_process_vm(struct task_struct *tsk,
 #else
                rc = get_user_pages(tsk, mm, addr, 1, write, 1, &page, &vma);
 #endif
-               if (rc <= 0)
+               if (rc <= 0 || !vma)
                        break;
 
                bytes = len;
@@ -383,7 +392,7 @@ out:
  * then an upcall could be issued here to get the jobid by utilizing
  * the userspace tools/API. Then, the jobid must be cached.
  */
-int jobid_get_from_environ(char *jobid_var, char *jobid, int *jobid_len)
+static int jobid_get_from_environ(char *jobid_var, char *jobid, int *jobid_len)
 {
        int rc;
 
@@ -442,13 +451,13 @@ static int jobid_should_free_item(void *obj, void *data)
                return 0;
 
        if (jobid == NULL) {
-               WARN_ON_ONCE(atomic_read(&pidmap->jp_refcount) != 1);
+               WARN_ON_ONCE(kref_read(&pidmap->jp_refcount) != 1);
                return 1;
        }
 
        spin_lock(&pidmap->jp_lock);
        /* prevent newly inserted items from deleting */
-       if (jobid[0] == '\0' && atomic_read(&pidmap->jp_refcount) == 1)
+       if (jobid[0] == '\0' && kref_read(&pidmap->jp_refcount) == 1)
                rc = 1;
        else if (ktime_get_real_seconds() - pidmap->jp_time > DELETE_INTERVAL)
                rc = 1;
@@ -470,7 +479,9 @@ static int jobid_should_free_item(void *obj, void *data)
 static bool jobid_name_is_valid(char *jobid)
 {
        const char *const lustre_reserved[] = { "ll_ping", "ptlrpc",
-                                               "ldlm", "ll_sa", NULL };
+                                               "ldlm", "ll_sa", "kworker",
+                                               "kswapd", "writeback", "irq",
+                                               "ksoftirq", NULL };
        int i;
 
        if (jobid[0] == '\0')
@@ -512,7 +523,7 @@ static int jobid_get_from_cache(char *jobid, size_t joblen)
                rcu_read_lock();
                jid = jobid_current();
                if (jid) {
-                       strlcpy(jobid, jid, joblen);
+                       strscpy(jobid, jid, joblen);
                        joblen = strlen(jobid);
                } else {
                        rc = -ENOENT;
@@ -554,7 +565,7 @@ static int jobid_get_from_cache(char *jobid, size_t joblen)
                 * hash list, init @jp_refcount as 1 to make sure memory
                 * could be not freed during access.
                 */
-               atomic_set(&pidmap->jp_refcount, 1);
+               kref_init(&pidmap->jp_refcount);
 
                /*
                 * Add the newly created map to the hash, on key collision we
@@ -591,7 +602,7 @@ static int jobid_get_from_cache(char *jobid, size_t joblen)
                spin_lock(&pidmap->jp_lock);
                if (!rc) {
                        pidmap->jp_joblen = env_len;
-                       strlcpy(pidmap->jp_jobid, env_jobid,
+                       strscpy(pidmap->jp_jobid, env_jobid,
                                sizeof(pidmap->jp_jobid));
                        rc = 0;
                } else if (rc == -ENOENT) {
@@ -608,7 +619,7 @@ static int jobid_get_from_cache(char *jobid, size_t joblen)
         * If a cached missing entry was found, return -ENOENT.
         */
        if (pidmap->jp_joblen) {
-               strlcpy(jobid, pidmap->jp_jobid, joblen);
+               strscpy(jobid, pidmap->jp_jobid, joblen);
                joblen = pidmap->jp_joblen;
                rc = 0;
        } else if (!rc) {
@@ -624,6 +635,31 @@ out:
 }
 
 /*
+ * jobid_print_current_comm()
+ *
+ * Print current comm name into the provided jobid buffer, and trim names of
+ * kernel threads like "kworker/0:0" to "kworker" or "ll_sa_12345" to "ll_sa"
+ *
+ * Return: number of chars printed to jobid
+ */
+static int jobid_print_current_comm(char *jobid, ssize_t joblen)
+{
+       const char *const names[] = {"kworker", "kswapd", "ll_sa", "ll_agl",
+                                    "ldlm_bl", NULL};
+       int i;
+
+       if (current->flags & PF_KTHREAD) {
+               for (i = 0; names[i] != NULL; i++) {
+                       if (strncmp(current->comm, names[i],
+                                   strlen(names[i])) == 0)
+                               return snprintf(jobid, joblen, "%s", names[i]);
+               }
+       }
+
+       return snprintf(jobid, joblen, "%s", current->comm);
+}
+
+/*
  * jobid_interpret_string()
  *
  * Interpret the jobfmt string to expand specified fields, like coredumps do:
@@ -663,7 +699,7 @@ static int jobid_interpret_string(const char *jobfmt, char *jobid,
 
                switch ((f = *jobfmt++)) {
                case 'e': /* executable name */
-                       l = snprintf(jobid, joblen, "%s", current->comm);
+                       l = jobid_print_current_comm(jobid, joblen);
                        break;
                case 'g': /* group ID */
                        l = snprintf(jobid, joblen, "%u",
@@ -775,10 +811,10 @@ EXPORT_SYMBOL(jobid_cache_fini);
 /*
  * Hash operations for pid<->jobid
  */
-static unsigned jobid_hashfn(struct cfs_hash *hs, const void *key,
-                            unsigned mask)
+static unsigned int
+jobid_hashfn(struct cfs_hash *hs, const void *key, const unsigned int bits)
 {
-       return cfs_hash_djb2_hash(key, sizeof(pid_t), mask);
+       return cfs_hash_djb2_hash(key, sizeof(pid_t), bits);
 }
 
 static void *jobid_key(struct hlist_node *hnode)
@@ -812,7 +848,16 @@ static void jobid_get(struct cfs_hash *hs, struct hlist_node *hnode)
 
        pidmap = hlist_entry(hnode, struct jobid_pid_map, jp_hash);
 
-       atomic_inc(&pidmap->jp_refcount);
+       kref_get(&pidmap->jp_refcount);
+}
+
+static void jobid_put_locked_free(struct kref *kref)
+{
+       struct jobid_pid_map *pidmap = container_of(kref, struct jobid_pid_map,
+                                                   jp_refcount);
+
+       CDEBUG(D_INFO, "Freeing: %d->%s\n", pidmap->jp_pid, pidmap->jp_jobid);
+       OBD_FREE_PTR(pidmap);
 }
 
 static void jobid_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
@@ -823,13 +868,8 @@ static void jobid_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
                return;
 
        pidmap = hlist_entry(hnode, struct jobid_pid_map, jp_hash);
-       LASSERT(atomic_read(&pidmap->jp_refcount) > 0);
-       if (atomic_dec_and_test(&pidmap->jp_refcount)) {
-               CDEBUG(D_INFO, "Freeing: %d->%s\n",
-                      pidmap->jp_pid, pidmap->jp_jobid);
-
-               OBD_FREE_PTR(pidmap);
-       }
+       LASSERT(kref_read(&pidmap->jp_refcount) > 0);
+       kref_put(&pidmap->jp_refcount, jobid_put_locked_free);
 }
 
 static struct cfs_hash_ops jobid_hash_ops = {
@@ -857,6 +897,8 @@ static struct cfs_hash_ops jobid_hash_ops = {
  */
 int lustre_get_jobid(char *jobid, size_t joblen)
 {
+       char id[LUSTRE_JOBID_SIZE] = "";
+       int len = min_t(int, joblen, LUSTRE_JOBID_SIZE);
        int rc = 0;
        ENTRY;
 
@@ -869,11 +911,14 @@ int lustre_get_jobid(char *jobid, size_t joblen)
        if (strcmp(obd_jobid_var, JOBSTATS_DISABLE) == 0) {
                /* Jobstats isn't enabled */
                memset(jobid, 0, joblen);
-       } else if (strcmp(obd_jobid_var, JOBSTATS_NODELOCAL) == 0) {
+               RETURN(0);
+       }
+
+       if (strcmp(obd_jobid_var, JOBSTATS_NODELOCAL) == 0) {
                /* Whole node dedicated to single job */
-               rc = jobid_interpret_string(obd_jobid_name, jobid, joblen);
+               rc = jobid_interpret_string(obd_jobid_name, id, len);
        } else if (strcmp(obd_jobid_var, JOBSTATS_PROCNAME_UID) == 0) {
-               rc = jobid_interpret_string("%e.%u", jobid, joblen);
+               rc = jobid_interpret_string("%e.%u", id, len);
        } else if (strcmp(obd_jobid_var, JOBSTATS_SESSION) == 0 ||
                   jobid_name_is_valid(current->comm)) {
                /*
@@ -884,17 +929,18 @@ int lustre_get_jobid(char *jobid, size_t joblen)
                 */
                rc = -EAGAIN;
                if (!strnstr(obd_jobid_name, "%j", joblen))
-                       rc = jobid_get_from_cache(jobid, joblen);
+                       rc = jobid_get_from_cache(id, len);
 
                /* fall back to jobid_name if jobid_var not available */
                if (rc < 0) {
                        int rc2 = jobid_interpret_string(obd_jobid_name,
-                                                        jobid, joblen);
+                                                        id, len);
                        if (!rc2)
                                rc = 0;
                }
        }
 
+       memcpy(jobid, id, len);
        RETURN(rc);
 }
 EXPORT_SYMBOL(lustre_get_jobid);
@@ -913,7 +959,7 @@ void lustre_jobid_clear(const char *find_jobid)
        if (jobid_hash == NULL)
                return;
 
-       strlcpy(jobid, find_jobid, sizeof(jobid));
+       strscpy(jobid, find_jobid, sizeof(jobid));
        /* trim \n off the end of the incoming jobid */
        end = strchr(jobid, '\n');
        if (end && *end == '\n')