diff -Naur orig/ipc/shm.c edited/ipc/shm.c --- orig/ipc/shm.c 2003-07-27 17:02:04.000000000 +0000 +++ edited/ipc/shm.c 2003-08-09 22:40:59.000000000 +0000 @@ -13,6 +13,7 @@ * Shared /dev/zero support, Kanoj Sarcar * Move the mm functionality over to mm/shmem.c, Christoph Rohland * + * sysfs support (c) 2003 Fabian Frederick */ #include @@ -27,6 +28,7 @@ #include #include #include +#include #include "util.h" @@ -56,14 +58,6 @@ static int shm_tot; /* total number of shared memory pages */ -void __init shm_init (void) -{ - ipc_init_ids(&shm_ids, 1); -#ifdef CONFIG_PROC_FS - create_proc_read_entry("sysvipc/shm", 0, 0, sysvipc_shm_read_proc, NULL); -#endif -} - static inline int shm_checkid(struct shmid_kernel *s, int id) { if (ipc_checkid(&shm_ids,&s->shm_perm,id)) @@ -81,8 +75,6 @@ return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1); } - - static inline void shm_inc (int id) { struct shmid_kernel *shp; @@ -93,6 +85,115 @@ shp->shm_nattch++; shm_unlock(shp); } +/* sysfs exports*/ + +#define SHM_ATTR(_name) \ +static struct attribute shm_attr_##_name={ \ + .name=__stringify(_name), \ + .mode=0444, \ +}; \ + +#define ATTR_TYPE(_name) \ +&shm_attr_##_name == attr + +SHM_ATTR(key); +SHM_ATTR(owner); +SHM_ATTR(bytes); +SHM_ATTR(perms); +SHM_ATTR(nattach); +SHM_ATTR(cpid); +SHM_ATTR(lpid); +SHM_ATTR(gid); +SHM_ATTR(cuid); +SHM_ATTR(cgid); +SHM_ATTR(atime); +SHM_ATTR(dtime); +SHM_ATTR(ctime); + +static struct attribute *shm_default_attrs[] = { + &shm_attr_key, + &shm_attr_owner, + &shm_attr_bytes, + &shm_attr_perms, + &shm_attr_nattach, + &shm_attr_cpid, + &shm_attr_lpid, + &shm_attr_gid, + &shm_attr_cuid, + &shm_attr_cgid, + &shm_attr_atime, + &shm_attr_dtime, + &shm_attr_ctime, + NULL, +}; + +static ssize_t shm_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + unsigned int id=simple_strtoul(kobj->name,NULL,10)%SEQ_MULTIPLIER; + long value; + struct shmid_kernel *shp; + down (&shm_ids.sem); + shp=shm_lock(id); + if(ATTR_TYPE(key)) + value=shp->shm_perm.key; + else if(ATTR_TYPE(owner)) + value=-1; + else if(ATTR_TYPE(bytes)) + value=(int)shp->shm_segsz; + else if(ATTR_TYPE(perms)) + value=shp->shm_perm.uid; + else if(ATTR_TYPE(nattach)) + value=is_file_hugepages \ + (shp->shm_file) ? (file_count(shp->shm_file)-1):\ + shp->shm_nattch; + else if(ATTR_TYPE(cpid)) + value=shp->shm_cprid; + else if(ATTR_TYPE(lpid)) + value=shp->shm_lprid; + else if(ATTR_TYPE(gid)) + value=shp->shm_perm.gid; + else if(ATTR_TYPE(cuid)) + value=shp->shm_perm.cuid; + else if(ATTR_TYPE(cgid)) + value=shp->shm_perm.cgid; + else if(ATTR_TYPE(atime)) + value=(long)shp->shm_atim; + else if(ATTR_TYPE(dtime)) + value=(long)shp->shm_dtim; + else if(ATTR_TYPE(ctime)) + value=(long) shp->shm_ctim; + else value=-1; + snprintf(buf, PAGE_SIZE, "%ld\n", value); + shm_unlock(shp); + up (&shm_ids.sem); + return strlen(buf); +} + +void shm_release (struct kobject *kobj) +{ + struct shmid_kernel *shp; + int id; + id=(int)simple_strtoul(kobj->name, NULL, 10); + shp = shm_lock(id); + shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; + shm_rmid (id); + shm_unlock(shp); + if (!is_file_hugepages(shp->shm_file)) + shmem_lock(shp->shm_file, 0); + fput (shp->shm_file); + security_shm_free(shp); + ipc_rcu_free(shp, sizeof(struct shmid_kernel)); +} + +static struct sysfs_ops shm_sysfs_ops ={ + .show = shm_attr_show, +}; + +static struct kobj_type shm_ktype ={ + .sysfs_ops = &shm_sysfs_ops, + .release = &shm_release, + .default_attrs = shm_default_attrs, +}; /* This is called by fork, once for every shm attach. */ static void shm_open (struct vm_area_struct *shmd) @@ -110,14 +211,8 @@ */ static void shm_destroy (struct shmid_kernel *shp) { - shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; - shm_rmid (shp->id); shm_unlock(shp); - if (!is_file_hugepages(shp->shm_file)) - shmem_lock(shp->shm_file, 0); - fput (shp->shm_file); - security_shm_free(shp); - ipc_rcu_free(shp, sizeof(struct shmid_kernel)); + kobject_unregister(&shm_ids.entries[shp->id%SEQ_MULTIPLIER].kobj); } /* @@ -165,6 +260,21 @@ .nopage = shmem_nopage, }; +void __init shm_init (void) +{ + ipc_init_ids(&shm_ids, 1); +#ifdef CONFIG_PROC_FS + create_proc_read_entry("sysvipc/shm", 0, 0, sysvipc_shm_read_proc, NULL); +#endif + memset(&shm_ids.kobj, 0, sizeof(struct kobject)); + strcpy(shm_ids.kobj.name, "shm"); + kobject_register(&shm_ids.kobj); + +} + + + /* Call with shm_ids.sem locked + */ static int newseg (key_t key, int shmflg, size_t size) { int error; @@ -223,7 +333,14 @@ else file->f_op = &shm_file_operations; shm_tot += numpages; + sprintf(shm_ids.entries[id].kobj.name, "%ld", \ + (long)shm_buildid(id,shp->shm_perm.seq)); + shm_ids.entries[id].kobj.parent=kobject_get(&shm_ids.kobj); + shm_ids.entries[id].kobj.kset=NULL; + shm_ids.entries[id].kobj.ktype=&shm_ktype; shm_unlock(shp); + if(kobject_register(&(shm_ids.entries[id].kobj))) + return -EINVAL; return shp->id; no_id: diff -Naur orig/ipc/util.h edited/ipc/util.h --- orig/ipc/util.h 2003-07-27 17:03:11.000000000 +0000 +++ edited/ipc/util.h 2003-07-29 06:51:51.000000000 +0000 @@ -19,9 +19,11 @@ unsigned short seq_max; struct semaphore sem; struct ipc_id* entries; + struct kobject kobj; /* sysfs/ipc/shm {,sem,msg...} */ }; struct ipc_id { + struct kobject kobj; /* sysfs/ipc/xxx/yyy */ struct kern_ipc_perm* p; };