Re: [RFC][PATCH 2 of 4] Configfs is really sysfs

2005-08-30 Thread Daniel Phillips
(avoiding the kmail formatting problems this time.)

Sysfs rearranged as a single file for analysis purposes.

diff -up --recursive 2.6.13-rc5-mm1.clean/fs/sysfs/Makefile 
2.6.13-rc5-mm1/fs/sysfs/Makefile
--- 2.6.13-rc5-mm1.clean/fs/sysfs/Makefile  2005-06-17 15:48:29.0 
-0400
+++ 2.6.13-rc5-mm1/fs/sysfs/Makefile2005-08-29 17:13:59.0 -0400
@@ -2,5 +2,4 @@
 # Makefile for the sysfs virtual filesystem
 #
 
-obj-y  := inode.o file.o dir.o symlink.o mount.o bin.o \
-  group.o
+obj-y := sysfs.o
diff -up --recursive 2.6.13-rc5-mm1.clean/fs/sysfs/sysfs.c 
2.6.13-rc5-mm1/fs/sysfs/sysfs.c
--- 2.6.13-rc5-mm1.clean/fs/sysfs/sysfs.c   2005-08-30 17:52:35.0 
-0400
+++ 2.6.13-rc5-mm1/fs/sysfs/sysfs.c 2005-08-29 21:04:40.0 -0400
@@ -0,0 +1,1680 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct sysfs_symlink {
+   char *link_name;
+   struct kobject *sl_target;
+};
+
+static inline struct kobject *to_kobj(struct dentry *dentry)
+{
+   struct sysfs_dirent *sd = dentry->d_fsdata;
+   return ((struct kobject *)sd->s_element);
+}
+
+static inline struct attribute *to_attr(struct dentry *dentry)
+{
+   struct sysfs_dirent *sd = dentry->d_fsdata;
+   return ((struct attribute *)sd->s_element);
+}
+
+static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
+{
+   struct kobject *kobj = NULL;
+
+   spin_lock(_lock);
+   if (!d_unhashed(dentry)) {
+   struct sysfs_dirent *sd = dentry->d_fsdata;
+   if (sd->s_type & SYSFS_KOBJ_LINK) {
+   struct sysfs_symlink *sl = sd->s_element;
+   kobj = kobject_get(sl->sl_target);
+   } else
+   kobj = kobject_get(sd->s_element);
+   }
+   spin_unlock(_lock);
+
+   return kobj;
+}
+
+static kmem_cache_t *sysfs_dir_cachep;
+
+static void release_sysfs_dirent(struct sysfs_dirent *sd)
+{
+   if (sd->s_type & SYSFS_KOBJ_LINK) {
+   struct sysfs_symlink *sl = sd->s_element;
+   kfree(sl->link_name);
+   kobject_put(sl->sl_target);
+   kfree(sl);
+   }
+   kfree(sd->s_iattr);
+   kmem_cache_free(sysfs_dir_cachep, sd);
+}
+
+static struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+   if (sd) {
+   WARN_ON(!atomic_read(>s_count));
+   atomic_inc(>s_count);
+   }
+   return sd;
+}
+
+static void sysfs_put(struct sysfs_dirent *sd)
+{
+   WARN_ON(!atomic_read(>s_count));
+   if (atomic_dec_and_test(>s_count))
+   release_sysfs_dirent(sd);
+}
+
+/*
+ * inode.c - basic inode and dentry operations.
+ */
+
+int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+   struct inode *inode = dentry->d_inode;
+   struct sysfs_dirent *sd = dentry->d_fsdata;
+   struct iattr *sd_iattr;
+   unsigned int ia_valid = iattr->ia_valid;
+   int error;
+
+   if (!sd)
+   return -EINVAL;
+
+   sd_iattr = sd->s_iattr;
+
+   error = inode_change_ok(inode, iattr);
+   if (error)
+   return error;
+
+   error = inode_setattr(inode, iattr);
+   if (error)
+   return error;
+
+   if (!sd_iattr) {
+   /* setting attributes for the first time, allocate now */
+   sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+   if (!sd_iattr)
+   return -ENOMEM;
+   /* assign default attributes */
+   memset(sd_iattr, 0, sizeof(struct iattr));
+   sd_iattr->ia_mode = sd->s_mode;
+   sd_iattr->ia_uid = 0;
+   sd_iattr->ia_gid = 0;
+   sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime =
+   CURRENT_TIME;
+   sd->s_iattr = sd_iattr;
+   }
+
+   /* attributes were changed atleast once in past */
+
+   if (ia_valid & ATTR_UID)
+   sd_iattr->ia_uid = iattr->ia_uid;
+   if (ia_valid & ATTR_GID)
+   sd_iattr->ia_gid = iattr->ia_gid;
+   if (ia_valid & ATTR_ATIME)
+   sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
+   inode->i_sb->s_time_gran);
+   if (ia_valid & ATTR_MTIME)
+   sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
+   inode->i_sb->s_time_gran);
+   if (ia_valid & ATTR_CTIME)
+   sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
+   inode->i_sb->s_time_gran);
+   if (ia_valid & ATTR_MODE) {
+   umode_t mode = iattr->ia_mode;
+
+   if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+   mode &= ~S_ISGID;
+   sd_iattr->ia_mode = sd->s_mode = mode;
+   }
+
+   return error;
+}
+

[RFC][PATCH 2 of 4] Configfs is really sysfs

2005-08-30 Thread Daniel Phillips
Sysfs rearranged as a single file for analysis purposes.

diff -up --recursive 2.6.13-rc5-mm1.clean/fs/sysfs/Makefile 
2.6.13-rc5-mm1/fs/sysfs/Makefile
--- 2.6.13-rc5-mm1.clean/fs/sysfs/Makefile 2005-06-17 15:48:29.0 -0400
+++ 2.6.13-rc5-mm1/fs/sysfs/Makefile 2005-08-29 17:13:59.0 -0400
@@ -2,5 +2,4 @@
 # Makefile for the sysfs virtual filesystem
 #
 
-obj-y  := inode.o file.o dir.o symlink.o mount.o bin.o \
- group.o
+obj-y := sysfs.o
diff -up --recursive 2.6.13-rc5-mm1.clean/fs/sysfs/sysfs.c 
2.6.13-rc5-mm1/fs/sysfs/sysfs.c
--- 2.6.13-rc5-mm1.clean/fs/sysfs/sysfs.c 2005-08-30 17:52:35.0 -0400
+++ 2.6.13-rc5-mm1/fs/sysfs/sysfs.c 2005-08-29 21:04:40.0 -0400
@@ -0,0 +1,1680 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct sysfs_symlink {
+ char *link_name;
+ struct kobject *sl_target;
+};
+
+static inline struct kobject *to_kobj(struct dentry *dentry)
+{
+ struct sysfs_dirent *sd = dentry->d_fsdata;
+ return ((struct kobject *)sd->s_element);
+}
+
+static inline struct attribute *to_attr(struct dentry *dentry)
+{
+   struct sysfs_dirent *sd = dentry->d_fsdata;
+   return ((struct attribute *)sd->s_element);
+}
+
+static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
+{
+   struct kobject *kobj = NULL;
+
+   spin_lock(_lock);
+   if (!d_unhashed(dentry)) {
+   struct sysfs_dirent *sd = dentry->d_fsdata;
+   if (sd->s_type & SYSFS_KOBJ_LINK) {
+   struct sysfs_symlink *sl = sd->s_element;
+   kobj = kobject_get(sl->sl_target);
+   } else
+   kobj = kobject_get(sd->s_element);
+   }
+   spin_unlock(_lock);
+
+   return kobj;
+}
+
+static kmem_cache_t *sysfs_dir_cachep;
+
+static void release_sysfs_dirent(struct sysfs_dirent *sd)
+{
+   if (sd->s_type & SYSFS_KOBJ_LINK) {
+   struct sysfs_symlink *sl = sd->s_element;
+   kfree(sl->link_name);
+   kobject_put(sl->sl_target);
+   kfree(sl);
+   }
+   kfree(sd->s_iattr);
+   kmem_cache_free(sysfs_dir_cachep, sd);
+}
+
+static struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+ if (sd) {
+  WARN_ON(!atomic_read(>s_count));
+  atomic_inc(>s_count);
+ }
+ return sd;
+}
+
+static void sysfs_put(struct sysfs_dirent *sd)
+{
+ WARN_ON(!atomic_read(>s_count));
+ if (atomic_dec_and_test(>s_count))
+  release_sysfs_dirent(sd);
+}
+
+/*
+ * inode.c - basic inode and dentry operations.
+ */
+
+int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+ struct inode *inode = dentry->d_inode;
+ struct sysfs_dirent *sd = dentry->d_fsdata;
+ struct iattr *sd_iattr;
+ unsigned int ia_valid = iattr->ia_valid;
+ int error;
+
+ if (!sd)
+  return -EINVAL;
+
+ sd_iattr = sd->s_iattr;
+
+ error = inode_change_ok(inode, iattr);
+ if (error)
+  return error;
+
+   error = inode_setattr(inode, iattr);
+   if (error)
+   return error;
+
+   if (!sd_iattr) {
+   /* setting attributes for the first time, allocate now */
+   sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+   if (!sd_iattr)
+   return -ENOMEM;
+   /* assign default attributes */
+   memset(sd_iattr, 0, sizeof(struct iattr));
+   sd_iattr->ia_mode = sd->s_mode;
+   sd_iattr->ia_uid = 0;
+   sd_iattr->ia_gid = 0;
+   sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime =
+   CURRENT_TIME;
+   sd->s_iattr = sd_iattr;
+   }
+
+   /* attributes were changed atleast once in past */
+
+   if (ia_valid & ATTR_UID)
+   sd_iattr->ia_uid = iattr->ia_uid;
+   if (ia_valid & ATTR_GID)
+   sd_iattr->ia_gid = iattr->ia_gid;
+   if (ia_valid & ATTR_ATIME)
+   sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
+   inode->i_sb->s_time_gran);
+   if (ia_valid & ATTR_MTIME)
+   sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
+  inode->i_sb->s_time_gran);
+ if (ia_valid & ATTR_CTIME)
+  sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
+  inode->i_sb->s_time_gran);
+ if (ia_valid & ATTR_MODE) {
+  umode_t mode = iattr->ia_mode;
+
+  if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+   mode &= ~S_ISGID;
+  sd_iattr->ia_mode = sd->s_mode = mode;
+ }
+
+ return error;
+}
+
+static struct inode_operations sysfs_inode_operations = {
+ .setattr = sysfs_setattr,
+};
+
+static struct super_block *sysfs_sb;
+
+static struct address_space_operations sysfs_aops = {
+ .readpage = simple_readpage,
+ .prepare_write = simple_prepare_write,
+ .commit_write = simple_commit_write
+};
+
+static struct backing_dev_info sysfs_backing_dev_info = {
+ .ra_pages = 0,  /* No readahead */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | 

[RFC][PATCH 2 of 4] Configfs is really sysfs

2005-08-30 Thread Daniel Phillips
Sysfs rearranged as a single file for analysis purposes.

diff -up --recursive 2.6.13-rc5-mm1.clean/fs/sysfs/Makefile 
2.6.13-rc5-mm1/fs/sysfs/Makefile
--- 2.6.13-rc5-mm1.clean/fs/sysfs/Makefile 2005-06-17 15:48:29.0 -0400
+++ 2.6.13-rc5-mm1/fs/sysfs/Makefile 2005-08-29 17:13:59.0 -0400
@@ -2,5 +2,4 @@
 # Makefile for the sysfs virtual filesystem
 #
 
-obj-y  := inode.o file.o dir.o symlink.o mount.o bin.o \
- group.o
+obj-y := sysfs.o
diff -up --recursive 2.6.13-rc5-mm1.clean/fs/sysfs/sysfs.c 
2.6.13-rc5-mm1/fs/sysfs/sysfs.c
--- 2.6.13-rc5-mm1.clean/fs/sysfs/sysfs.c 2005-08-30 17:52:35.0 -0400
+++ 2.6.13-rc5-mm1/fs/sysfs/sysfs.c 2005-08-29 21:04:40.0 -0400
@@ -0,0 +1,1680 @@
+#include linux/fs.h
+#include linux/namei.h
+#include linux/module.h
+#include linux/mount.h
+#include linux/backing-dev.h
+#include linux/pagemap.h
+#include linux/fsnotify.h
+
+struct sysfs_symlink {
+ char *link_name;
+ struct kobject *sl_target;
+};
+
+static inline struct kobject *to_kobj(struct dentry *dentry)
+{
+ struct sysfs_dirent *sd = dentry-d_fsdata;
+ return ((struct kobject *)sd-s_element);
+}
+
+static inline struct attribute *to_attr(struct dentry *dentry)
+{
+   struct sysfs_dirent *sd = dentry-d_fsdata;
+   return ((struct attribute *)sd-s_element);
+}
+
+static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
+{
+   struct kobject *kobj = NULL;
+
+   spin_lock(dcache_lock);
+   if (!d_unhashed(dentry)) {
+   struct sysfs_dirent *sd = dentry-d_fsdata;
+   if (sd-s_type  SYSFS_KOBJ_LINK) {
+   struct sysfs_symlink *sl = sd-s_element;
+   kobj = kobject_get(sl-sl_target);
+   } else
+   kobj = kobject_get(sd-s_element);
+   }
+   spin_unlock(dcache_lock);
+
+   return kobj;
+}
+
+static kmem_cache_t *sysfs_dir_cachep;
+
+static void release_sysfs_dirent(struct sysfs_dirent *sd)
+{
+   if (sd-s_type  SYSFS_KOBJ_LINK) {
+   struct sysfs_symlink *sl = sd-s_element;
+   kfree(sl-link_name);
+   kobject_put(sl-sl_target);
+   kfree(sl);
+   }
+   kfree(sd-s_iattr);
+   kmem_cache_free(sysfs_dir_cachep, sd);
+}
+
+static struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+ if (sd) {
+  WARN_ON(!atomic_read(sd-s_count));
+  atomic_inc(sd-s_count);
+ }
+ return sd;
+}
+
+static void sysfs_put(struct sysfs_dirent *sd)
+{
+ WARN_ON(!atomic_read(sd-s_count));
+ if (atomic_dec_and_test(sd-s_count))
+  release_sysfs_dirent(sd);
+}
+
+/*
+ * inode.c - basic inode and dentry operations.
+ */
+
+int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+ struct inode *inode = dentry-d_inode;
+ struct sysfs_dirent *sd = dentry-d_fsdata;
+ struct iattr *sd_iattr;
+ unsigned int ia_valid = iattr-ia_valid;
+ int error;
+
+ if (!sd)
+  return -EINVAL;
+
+ sd_iattr = sd-s_iattr;
+
+ error = inode_change_ok(inode, iattr);
+ if (error)
+  return error;
+
+   error = inode_setattr(inode, iattr);
+   if (error)
+   return error;
+
+   if (!sd_iattr) {
+   /* setting attributes for the first time, allocate now */
+   sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+   if (!sd_iattr)
+   return -ENOMEM;
+   /* assign default attributes */
+   memset(sd_iattr, 0, sizeof(struct iattr));
+   sd_iattr-ia_mode = sd-s_mode;
+   sd_iattr-ia_uid = 0;
+   sd_iattr-ia_gid = 0;
+   sd_iattr-ia_atime = sd_iattr-ia_mtime = sd_iattr-ia_ctime =
+   CURRENT_TIME;
+   sd-s_iattr = sd_iattr;
+   }
+
+   /* attributes were changed atleast once in past */
+
+   if (ia_valid  ATTR_UID)
+   sd_iattr-ia_uid = iattr-ia_uid;
+   if (ia_valid  ATTR_GID)
+   sd_iattr-ia_gid = iattr-ia_gid;
+   if (ia_valid  ATTR_ATIME)
+   sd_iattr-ia_atime = timespec_trunc(iattr-ia_atime,
+   inode-i_sb-s_time_gran);
+   if (ia_valid  ATTR_MTIME)
+   sd_iattr-ia_mtime = timespec_trunc(iattr-ia_mtime,
+  inode-i_sb-s_time_gran);
+ if (ia_valid  ATTR_CTIME)
+  sd_iattr-ia_ctime = timespec_trunc(iattr-ia_ctime,
+  inode-i_sb-s_time_gran);
+ if (ia_valid  ATTR_MODE) {
+  umode_t mode = iattr-ia_mode;
+
+  if (!in_group_p(inode-i_gid)  !capable(CAP_FSETID))
+   mode = ~S_ISGID;
+  sd_iattr-ia_mode = sd-s_mode = mode;
+ }
+
+ return error;
+}
+
+static struct inode_operations sysfs_inode_operations = {
+ .setattr = sysfs_setattr,
+};
+
+static struct super_block *sysfs_sb;
+
+static struct address_space_operations sysfs_aops = {
+ .readpage = simple_readpage,
+ .prepare_write = simple_prepare_write,
+ .commit_write = simple_commit_write
+};
+
+static struct backing_dev_info sysfs_backing_dev_info = {
+ .ra_pages = 0,  /* 

Re: [RFC][PATCH 2 of 4] Configfs is really sysfs

2005-08-30 Thread Daniel Phillips
(avoiding the kmail formatting problems this time.)

Sysfs rearranged as a single file for analysis purposes.

diff -up --recursive 2.6.13-rc5-mm1.clean/fs/sysfs/Makefile 
2.6.13-rc5-mm1/fs/sysfs/Makefile
--- 2.6.13-rc5-mm1.clean/fs/sysfs/Makefile  2005-06-17 15:48:29.0 
-0400
+++ 2.6.13-rc5-mm1/fs/sysfs/Makefile2005-08-29 17:13:59.0 -0400
@@ -2,5 +2,4 @@
 # Makefile for the sysfs virtual filesystem
 #
 
-obj-y  := inode.o file.o dir.o symlink.o mount.o bin.o \
-  group.o
+obj-y := sysfs.o
diff -up --recursive 2.6.13-rc5-mm1.clean/fs/sysfs/sysfs.c 
2.6.13-rc5-mm1/fs/sysfs/sysfs.c
--- 2.6.13-rc5-mm1.clean/fs/sysfs/sysfs.c   2005-08-30 17:52:35.0 
-0400
+++ 2.6.13-rc5-mm1/fs/sysfs/sysfs.c 2005-08-29 21:04:40.0 -0400
@@ -0,0 +1,1680 @@
+#include linux/fs.h
+#include linux/namei.h
+#include linux/module.h
+#include linux/mount.h
+#include linux/backing-dev.h
+#include linux/pagemap.h
+#include linux/fsnotify.h
+
+struct sysfs_symlink {
+   char *link_name;
+   struct kobject *sl_target;
+};
+
+static inline struct kobject *to_kobj(struct dentry *dentry)
+{
+   struct sysfs_dirent *sd = dentry-d_fsdata;
+   return ((struct kobject *)sd-s_element);
+}
+
+static inline struct attribute *to_attr(struct dentry *dentry)
+{
+   struct sysfs_dirent *sd = dentry-d_fsdata;
+   return ((struct attribute *)sd-s_element);
+}
+
+static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
+{
+   struct kobject *kobj = NULL;
+
+   spin_lock(dcache_lock);
+   if (!d_unhashed(dentry)) {
+   struct sysfs_dirent *sd = dentry-d_fsdata;
+   if (sd-s_type  SYSFS_KOBJ_LINK) {
+   struct sysfs_symlink *sl = sd-s_element;
+   kobj = kobject_get(sl-sl_target);
+   } else
+   kobj = kobject_get(sd-s_element);
+   }
+   spin_unlock(dcache_lock);
+
+   return kobj;
+}
+
+static kmem_cache_t *sysfs_dir_cachep;
+
+static void release_sysfs_dirent(struct sysfs_dirent *sd)
+{
+   if (sd-s_type  SYSFS_KOBJ_LINK) {
+   struct sysfs_symlink *sl = sd-s_element;
+   kfree(sl-link_name);
+   kobject_put(sl-sl_target);
+   kfree(sl);
+   }
+   kfree(sd-s_iattr);
+   kmem_cache_free(sysfs_dir_cachep, sd);
+}
+
+static struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+   if (sd) {
+   WARN_ON(!atomic_read(sd-s_count));
+   atomic_inc(sd-s_count);
+   }
+   return sd;
+}
+
+static void sysfs_put(struct sysfs_dirent *sd)
+{
+   WARN_ON(!atomic_read(sd-s_count));
+   if (atomic_dec_and_test(sd-s_count))
+   release_sysfs_dirent(sd);
+}
+
+/*
+ * inode.c - basic inode and dentry operations.
+ */
+
+int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+   struct inode *inode = dentry-d_inode;
+   struct sysfs_dirent *sd = dentry-d_fsdata;
+   struct iattr *sd_iattr;
+   unsigned int ia_valid = iattr-ia_valid;
+   int error;
+
+   if (!sd)
+   return -EINVAL;
+
+   sd_iattr = sd-s_iattr;
+
+   error = inode_change_ok(inode, iattr);
+   if (error)
+   return error;
+
+   error = inode_setattr(inode, iattr);
+   if (error)
+   return error;
+
+   if (!sd_iattr) {
+   /* setting attributes for the first time, allocate now */
+   sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+   if (!sd_iattr)
+   return -ENOMEM;
+   /* assign default attributes */
+   memset(sd_iattr, 0, sizeof(struct iattr));
+   sd_iattr-ia_mode = sd-s_mode;
+   sd_iattr-ia_uid = 0;
+   sd_iattr-ia_gid = 0;
+   sd_iattr-ia_atime = sd_iattr-ia_mtime = sd_iattr-ia_ctime =
+   CURRENT_TIME;
+   sd-s_iattr = sd_iattr;
+   }
+
+   /* attributes were changed atleast once in past */
+
+   if (ia_valid  ATTR_UID)
+   sd_iattr-ia_uid = iattr-ia_uid;
+   if (ia_valid  ATTR_GID)
+   sd_iattr-ia_gid = iattr-ia_gid;
+   if (ia_valid  ATTR_ATIME)
+   sd_iattr-ia_atime = timespec_trunc(iattr-ia_atime,
+   inode-i_sb-s_time_gran);
+   if (ia_valid  ATTR_MTIME)
+   sd_iattr-ia_mtime = timespec_trunc(iattr-ia_mtime,
+   inode-i_sb-s_time_gran);
+   if (ia_valid  ATTR_CTIME)
+   sd_iattr-ia_ctime = timespec_trunc(iattr-ia_ctime,
+   inode-i_sb-s_time_gran);
+   if (ia_valid  ATTR_MODE) {
+   umode_t mode = iattr-ia_mode;
+
+   if (!in_group_p(inode-i_gid)  !capable(CAP_FSETID))
+   mode = ~S_ISGID;
+   sd_iattr-ia_mode