gpu: pvr: improve per process procfs entry/dir handling
authorLuc Verhaegen <libv@codethink.co.uk>
Mon, 21 Feb 2011 12:07:26 +0000 (13:07 +0100)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 20 May 2012 18:43:03 +0000 (21:43 +0300)
When building with full debug, a lot of "Resource Arena" (ra) data is
being made available in the rather painful procfs, including per process
ra info, kept in process specific subdirectories.

Adding and removing process specific entries from procfs took the PID of
the currently running process; which sometimes failed during cleanup,
when the current process might no longer be anything tracked by the
driver. This then resulted in some strange behaviour, where it was
impossible to cleanup a process specific procfs directory, resulting
in an endless loop.

Since process specific procfs entries are only created in the RA code,
we now track the pid in the RA struct. When we pass this pid to
both the procfs entry creation and removal functions, we now do
reliably clean up the procfs entries.

Signed-off-by: Luc Verhaegen <libv@codethink.co.uk>
Signed-off-by: Imre Deak <imre.deak@nokia.com>
pvr/proc.c
pvr/proc.h
pvr/ra.c

index 613d3de..a8564f0 100644 (file)
@@ -138,59 +138,78 @@ int CreateProcEntry(const char *name, read_proc_t rhandler,
        return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
 }
 
-int CreatePerProcessProcEntry(const char *name, read_proc_t rhandler,
-                             write_proc_t whandler, void *data)
+static struct proc_dir_entry *
+ProcessProcDirCreate(u32 pid)
 {
        struct PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
-       u32 ui32PID;
+       char dirname[16];
+       int ret;
 
-       if (!dir) {
-               PVR_DPF(PVR_DBG_ERROR,
-                        "CreatePerProcessProcEntries: /proc/%s doesn't exist",
-                        PVRProcDirRoot);
+       psPerProc = PVRSRVPerProcessPrivateData(pid);
+       if (!psPerProc) {
+               pr_err("%s: no per process data for %d\n", __func__, pid);
+               return NULL;
+       }
 
-               return -ENOMEM;
+       if (psPerProc->psProcDir)
+               return psPerProc->psProcDir;
+
+       ret = snprintf(dirname, sizeof(dirname), "%u", pid);
+       if (ret <= 0 || ret >= sizeof(dirname)) {
+               pr_err("%s: couldn't generate per process proc dir for %d\n",
+                      __func__, pid);
+               return NULL;
        }
 
-       ui32PID = OSGetCurrentProcessIDKM();
+       psPerProc->psProcDir = proc_mkdir(dirname, dir);
+       if (!psPerProc->psProcDir)
+               pr_err("%s: couldn't create /proc/%s/%u\n",
+                      __func__, PVRProcDirRoot, pid);
 
-       psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
-       if (!psPerProc) {
-               PVR_DPF(PVR_DBG_ERROR,
-                        "CreatePerProcessProcEntries: no per process data");
+       return psPerProc->psProcDir;
+}
 
-               return -ENOMEM;
+static struct proc_dir_entry *
+ProcessProcDirGet(u32 pid)
+{
+       struct PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+       psPerProc = PVRSRVPerProcessPrivateData(pid);
+       if (!psPerProc) {
+               pr_err("%s: no per process data for %d\n", __func__, pid);
+               return NULL;
        }
 
        if (!psPerProc->psProcDir) {
-               char dirname[16];
-               int ret;
+               pr_err("%s: couldn't retrieve /proc/%s/%u\n", __func__,
+                      PVRProcDirRoot, pid);
+               return NULL;
+       }
 
-               ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+       return psPerProc->psProcDir;
+}
 
-               if (ret <= 0 || ret >= sizeof(dirname)) {
-                       PVR_DPF(PVR_DBG_ERROR, "CreatePerProcessProcEntries: "
-                                       "couldn't generate per process proc "
-                                       "directory name \"%u\"",
-                                        ui32PID);
+int CreatePerProcessProcEntry(u32 pid, const char *name, read_proc_t rhandler,
+                             void *data)
+{
+       if (!dir) {
+               PVR_DPF(PVR_DBG_ERROR,
+                        "CreatePerProcessProcEntries: /proc/%s doesn't exist",
+                        PVRProcDirRoot);
 
-                       return -ENOMEM;
-               } else {
-                       psPerProc->psProcDir = proc_mkdir(dirname, dir);
-                       if (!psPerProc->psProcDir) {
-                               PVR_DPF(PVR_DBG_ERROR,
-                                       "CreatePerProcessProcEntries: "
-                                       "couldn't create per process proc "
-                                       "directory /proc/%s/%u",
-                                        PVRProcDirRoot, ui32PID);
-
-                               return -ENOMEM;
-                       }
-               }
+               return -ENOMEM;
        }
 
-       return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler,
-                                   whandler, data);
+       if (pid) {
+               struct proc_dir_entry *pid_dir = ProcessProcDirCreate(pid);
+
+               if (!pid_dir)
+                       return -ENOMEM;
+
+               return CreateProcEntryInDir(pid_dir, name, rhandler, NULL,
+                                           data);
+       } else
+               return CreateProcEntryInDir(dir, name, rhandler, NULL, data);
 }
 
 int CreateProcReadEntry(const char *name,
@@ -264,24 +283,20 @@ void RemoveProcEntry(const char *name)
        }
 }
 
-void RemovePerProcessProcEntry(const char *name)
+void RemovePerProcessProcEntry(u32 pid, const char *name)
 {
-       struct PVRSRV_ENV_PER_PROCESS_DATA *psPerProc =
-           PVRSRVFindPerProcessPrivateData();
+       if (pid) {
+               struct proc_dir_entry *pid_dir = ProcessProcDirGet(pid);
 
-       if (!psPerProc) {
-               PVR_DPF(PVR_DBG_ERROR, "CreatePerProcessProcEntries: "
-                                       "can't remove %s, no per process data",
-                        name);
-               return;
-       }
+               if (!pid_dir)
+                       return;
 
-       if (psPerProc->psProcDir) {
-               remove_proc_entry(name, psPerProc->psProcDir);
+               remove_proc_entry(name, pid_dir);
 
                PVR_DPF(PVR_DBG_MESSAGE, "Removing proc entry %s from %s",
-                        name, psPerProc->psProcDir->name);
-       }
+                        name, pid_dir->name);
+       } else
+               RemoveProcEntry(name);
 }
 
 void RemovePerProcessProcDir(struct PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
index 942b2ea..c93543c 100644 (file)
@@ -42,12 +42,12 @@ int CreateProcReadEntry(const char *name,
 int CreateProcEntry(const char *name, read_proc_t rhandler,
                    write_proc_t whandler, void *data);
 
-int CreatePerProcessProcEntry(const char *name, read_proc_t rhandler,
-                             write_proc_t whandler, void *data);
+int CreatePerProcessProcEntry(u32 pid, const char *name, read_proc_t rhandler,
+                             void *data);
 
 void RemoveProcEntry(const char *name);
 
-void RemovePerProcessProcEntry(const char *name);
+void RemovePerProcessProcEntry(u32 pid, const char *name);
 
 void RemoveProcEntries(void);
 
index 4c71af1..bcd96b8 100644 (file)
--- a/pvr/ra.c
+++ b/pvr/ra.c
@@ -77,7 +77,7 @@ struct RA_ARENA {
 #define PROC_NAME_SIZE         32
        char szProcInfoName[PROC_NAME_SIZE];
        char szProcSegsName[PROC_NAME_SIZE];
-       IMG_BOOL bInitProcEntry;
+       u32 ui32PID;
 #endif
 };
 
@@ -644,41 +644,44 @@ struct RA_ARENA *RA_Create(char *name, u32 base, size_t uSize,
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
        if (strcmp(pArena->name, "") != 0) {
                int ret;
-               int (*pfnCreateProcEntry) (const char *, read_proc_t,
-                                          write_proc_t, void *);
 
-               pArena->bInitProcEntry =
-                   !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
-
-               pfnCreateProcEntry = pArena->bInitProcEntry ? CreateProcEntry :
-                                           CreatePerProcessProcEntry;
+               if (PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+                       pArena->ui32PID = OSGetCurrentProcessIDKM();
+               else
+                       pArena->ui32PID = 0;
 
                ret = snprintf(pArena->szProcInfoName,
                             sizeof(pArena->szProcInfoName), "ra_info_%s",
                             pArena->name);
-               if (ret > 0 && ret < sizeof(pArena->szProcInfoName)) {
-                       (void)pfnCreateProcEntry(ReplaceSpaces
-                                              (pArena->szProcInfoName),
-                                              RA_DumpInfo, NULL, pArena);
-               } else {
+               if ((ret > 0) && (ret < sizeof(pArena->szProcInfoName))) {
+                       ReplaceSpaces(pArena->szProcInfoName);
+                       ret = CreatePerProcessProcEntry(pArena->ui32PID,
+                                                       pArena->szProcInfoName,
+                                                       RA_DumpInfo, pArena);
+               } else
+                       pArena->szProcInfoName[0] = 0;
+
+               if (ret) {
                        pArena->szProcInfoName[0] = 0;
-                       PVR_DPF(PVR_DBG_ERROR, "RA_Create: "
-                             "couldn't create ra_info proc entry for arena %s",
-                                pArena->name);
+                       pr_err("%s: couldn't create ra_info proc entry for "
+                              "arena %s", __func__, pArena->name);
                }
 
                ret = snprintf(pArena->szProcSegsName,
                             sizeof(pArena->szProcSegsName), "ra_segs_%s",
                             pArena->name);
-               if (ret > 0 && ret < sizeof(pArena->szProcInfoName)) {
-                       (void)pfnCreateProcEntry(ReplaceSpaces
-                                              (pArena->szProcSegsName),
-                                              RA_DumpSegs, NULL, pArena);
-               } else {
+               if ((ret > 0) && (ret < sizeof(pArena->szProcSegsName))) {
+                       ReplaceSpaces(pArena->szProcSegsName);
+                       ret = CreatePerProcessProcEntry(pArena->ui32PID,
+                                                       pArena->szProcSegsName,
+                                                       RA_DumpSegs, pArena);
+               } else
+                       ret = -1;
+
+               if (ret) {
                        pArena->szProcSegsName[0] = 0;
-                       PVR_DPF(PVR_DBG_ERROR, "RA_Create: "
-                             "couldn't create ra_segs proc entry for arena %s",
-                                pArena->name);
+                       pr_err("%s: couldn't create ra_segs proc entry for "
+                              "arena %s", __func__, pArena->name);
                }
        }
 #endif
@@ -734,18 +737,13 @@ void RA_Delete(struct RA_ARENA *pArena)
        }
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
        {
-               void (*pfnRemoveProcEntry) (const char *);
-
-               pfnRemoveProcEntry =
-                   pArena->
-                   bInitProcEntry ? RemoveProcEntry :
-                   RemovePerProcessProcEntry;
-
                if (pArena->szProcInfoName[0] != 0)
-                       pfnRemoveProcEntry(pArena->szProcInfoName);
+                       RemovePerProcessProcEntry(pArena->ui32PID,
+                                                 pArena->szProcInfoName);
 
                if (pArena->szProcSegsName[0] != 0)
-                       pfnRemoveProcEntry(pArena->szProcSegsName);
+                       RemovePerProcessProcEntry(pArena->ui32PID,
+                                                 pArena->szProcSegsName);
        }
 #endif
        HASH_Delete(pArena->pSegmentHash);