Tejun Heo <[EMAIL PROTECTED]> writes: > Eric W. Biederman wrote: >> What do we use inode->i_mutex for? I think we might be able >> to kill that. >> >> I'm starting to wonder if we can completely remove sysfs >> from grabbing inode->i_mutex. > > i_mutex is grabbed when dentry and inode locking requires it. It's not > used to protect sysfs internal data structure anymore. I don't think we > can remove i_mutex grabbing without violating dentry/inode locking rules.
Not entirely no. I think we can remove i_mutex from protecting dentry tree modifications. >>>> At first glance sysfs_assoc_lock looks just as bad. >>> I think sysfs_assoc_lock is okay. It's tricky tho. Why do you think >>> it's bad? >> >> I'm still looking. I just have a weird vibe so far. sysfs_get_dentry >> is really nasty with respect to locking. > > Yes, sysfs_get_dentry() is pretty hairy. I wish I could use > path_lookup() there but can't allocate memory for path name because > looking up must succeed when it's called from removal path if dentry > already exists. Also, lookup_one_len_kern() bypasses security checks > and there's no equivalent path_lookup() like function which does that. We can use d_hash_and_lookup and that helps a lot. I have attached my in-progress rewrite of sysfs_get_dentry. It's a little less efficient but a whole lot easier to maintain. > Locking rule aruond sysfs_assoc_lock is tricky. It's mainly used to > avoid race condition between sysfs_d_iput() vs. dentry creation, node > removal, etc. As long as sysfs_assoc_lock is held, sd->s_dentry can be > dereferenced but you also need dcache_lock to determine whether the > dentry is alive (dentry->d_inode != NULL) or in the process of being > killed. There were two or three race conditions around dentry > reclamation in the past and several discussion threads about them. I think I have figured out how to safely remove s_dentry entirely from sysfs_dirent and that winds up removing a lot of subtle and nasty locking. I'm hoping to have a good patch series after another couple of hours of work. struct dentry *__sysfs_get_dentry(struct sysfs_dirent *sd, int create) { struct sysfs_dirent *cur; struct dentry *parent_dentry, *dentry; struct qstr name; struct inode *inode; parent_dentry = NULL; dentry = dget(sysfs_sb->s_root); do { /* Find the first ancestor I have not looked up */ cur = sd; while (cur->s_parent != dentry->d_fsdata) cur = cur->s_parent; /* look it up */ dput(parent_dentry); parent_dentry = dentry; name.name = cur->s_name; name.len = strlen(cur->s_name); dentry = d_hash_and_lookup(parent_dentry, &name); if (dentry) continue; if (!create) goto out; dentry = d_alloc(parent_dentry, &name); if (!dentry) { dentry = ERR_PTR(-ENOMEM); goto out; } inode = sysfs_get_inode(cur); if (!inode) { dput(dentry); dentry = ERR_PTR(-ENOMEM); goto out; } d_instantiate(dentry, inode); sysfs_attach_dentry(cur, dentry); } while (cur != sd); out: dput(parent_dentry); return dentry; } struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) { struct dentry *dentry; mutex_lock(&sysfs_mutex); dentry = __sysfs_get_dentry(sd, 1); mutex_unlock(&sysfs_mutex); return dentry; } Eric _______________________________________________ Containers mailing list [EMAIL PROTECTED] https://lists.linux-foundation.org/mailman/listinfo/containers _______________________________________________ Devel mailing list Devel@openvz.org https://openvz.org/mailman/listinfo/devel