Revert "kernfs: invoke kernfs_unmap_bin_file() directly from __kernfs_remove()"
[deliverable/linux.git] / fs / kernfs / file.c
index 990c97fa7045c2a1f17dd13fe22d7b27c04e9791..231a171f48b6f107f729594a82165f4973e56073 100644 (file)
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/pagemap.h>
-#include <linux/poll.h>
 #include <linux/sched.h>
 
 #include "kernfs-internal.h"
 
 /*
- * There's one sysfs_open_file for each open file and one sysfs_open_dirent
- * for each sysfs_dirent with one or more open files.
+ * There's one kernfs_open_file for each open file and one kernfs_open_node
+ * for each kernfs_node with one or more open files.
  *
- * sysfs_dirent->s_attr.open points to sysfs_open_dirent.  s_attr.open is
- * protected by sysfs_open_dirent_lock.
+ * kernfs_node->attr.open points to kernfs_open_node.  attr.open is
+ * protected by kernfs_open_node_lock.
  *
  * filp->private_data points to seq_file whose ->private points to
- * sysfs_open_file.  sysfs_open_files are chained at
- * sysfs_open_dirent->files, which is protected by sysfs_open_file_mutex.
+ * kernfs_open_file.  kernfs_open_files are chained at
+ * kernfs_open_node->files, which is protected by kernfs_open_file_mutex.
  */
-static DEFINE_SPINLOCK(sysfs_open_dirent_lock);
-static DEFINE_MUTEX(sysfs_open_file_mutex);
+static DEFINE_SPINLOCK(kernfs_open_node_lock);
+static DEFINE_MUTEX(kernfs_open_file_mutex);
 
-struct sysfs_open_dirent {
+struct kernfs_open_node {
        atomic_t                refcnt;
        atomic_t                event;
        wait_queue_head_t       poll;
-       struct list_head        files; /* goes through sysfs_open_file.list */
+       struct list_head        files; /* goes through kernfs_open_file.list */
 };
 
-static struct sysfs_open_file *sysfs_of(struct file *file)
+static struct kernfs_open_file *kernfs_of(struct file *file)
 {
        return ((struct seq_file *)file->private_data)->private;
 }
 
 /*
- * Determine the kernfs_ops for the given sysfs_dirent.  This function must
+ * Determine the kernfs_ops for the given kernfs_node.  This function must
  * be called while holding an active reference.
  */
-static const struct kernfs_ops *kernfs_ops(struct sysfs_dirent *sd)
+static const struct kernfs_ops *kernfs_ops(struct kernfs_node *kn)
 {
-       if (sd->s_flags & SYSFS_FLAG_LOCKDEP)
-               lockdep_assert_held(sd);
-       return sd->s_attr.ops;
+       if (kn->flags & KERNFS_LOCKDEP)
+               lockdep_assert_held(kn);
+       return kn->attr.ops;
+}
+
+/*
+ * As kernfs_seq_stop() is also called after kernfs_seq_start() or
+ * kernfs_seq_next() failure, it needs to distinguish whether it's stopping
+ * a seq_file iteration which is fully initialized with an active reference
+ * or an aborted kernfs_seq_start() due to get_active failure.  The
+ * position pointer is the only context for each seq_file iteration and
+ * thus the stop condition should be encoded in it.  As the return value is
+ * directly visible to userland, ERR_PTR(-ENODEV) is the only acceptable
+ * choice to indicate get_active failure.
+ *
+ * Unfortunately, this is complicated due to the optional custom seq_file
+ * operations which may return ERR_PTR(-ENODEV) too.  kernfs_seq_stop()
+ * can't distinguish whether ERR_PTR(-ENODEV) is from get_active failure or
+ * custom seq_file operations and thus can't decide whether put_active
+ * should be performed or not only on ERR_PTR(-ENODEV).
+ *
+ * This is worked around by factoring out the custom seq_stop() and
+ * put_active part into kernfs_seq_stop_active(), skipping it from
+ * kernfs_seq_stop() if ERR_PTR(-ENODEV) while invoking it directly after
+ * custom seq_file operations fail with ERR_PTR(-ENODEV) - this ensures
+ * that kernfs_seq_stop_active() is skipped only after get_active failure.
+ */
+static void kernfs_seq_stop_active(struct seq_file *sf, void *v)
+{
+       struct kernfs_open_file *of = sf->private;
+       const struct kernfs_ops *ops = kernfs_ops(of->kn);
+
+       if (ops->seq_stop)
+               ops->seq_stop(sf, v);
+       kernfs_put_active(of->kn);
 }
 
 static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos)
 {
-       struct sysfs_open_file *of = sf->private;
+       struct kernfs_open_file *of = sf->private;
        const struct kernfs_ops *ops;
 
        /*
@@ -65,12 +96,16 @@ static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos)
         * the ops aren't called concurrently for the same open file.
         */
        mutex_lock(&of->mutex);
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                return ERR_PTR(-ENODEV);
 
-       ops = kernfs_ops(of->sd);
+       ops = kernfs_ops(of->kn);
        if (ops->seq_start) {
-               return ops->seq_start(sf, ppos);
+               void *next = ops->seq_start(sf, ppos);
+               /* see the comment above kernfs_seq_stop_active() */
+               if (next == ERR_PTR(-ENODEV))
+                       kernfs_seq_stop_active(sf, next);
+               return next;
        } else {
                /*
                 * The same behavior and code as single_open().  Returns
@@ -82,11 +117,15 @@ static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos)
 
 static void *kernfs_seq_next(struct seq_file *sf, void *v, loff_t *ppos)
 {
-       struct sysfs_open_file *of = sf->private;
-       const struct kernfs_ops *ops = kernfs_ops(of->sd);
+       struct kernfs_open_file *of = sf->private;
+       const struct kernfs_ops *ops = kernfs_ops(of->kn);
 
        if (ops->seq_next) {
-               return ops->seq_next(sf, v, ppos);
+               void *next = ops->seq_next(sf, v, ppos);
+               /* see the comment above kernfs_seq_stop_active() */
+               if (next == ERR_PTR(-ENODEV))
+                       kernfs_seq_stop_active(sf, next);
+               return next;
        } else {
                /*
                 * The same behavior and code as single_open(), always
@@ -99,23 +138,20 @@ static void *kernfs_seq_next(struct seq_file *sf, void *v, loff_t *ppos)
 
 static void kernfs_seq_stop(struct seq_file *sf, void *v)
 {
-       struct sysfs_open_file *of = sf->private;
-       const struct kernfs_ops *ops = kernfs_ops(of->sd);
-
-       if (ops->seq_stop)
-               ops->seq_stop(sf, v);
+       struct kernfs_open_file *of = sf->private;
 
-       sysfs_put_active(of->sd);
+       if (v != ERR_PTR(-ENODEV))
+               kernfs_seq_stop_active(sf, v);
        mutex_unlock(&of->mutex);
 }
 
 static int kernfs_seq_show(struct seq_file *sf, void *v)
 {
-       struct sysfs_open_file *of = sf->private;
+       struct kernfs_open_file *of = sf->private;
 
-       of->event = atomic_read(&of->sd->s_attr.open->event);
+       of->event = atomic_read(&of->kn->attr.open->event);
 
-       return of->sd->s_attr.ops->seq_show(sf, v);
+       return of->kn->attr.ops->seq_show(sf, v);
 }
 
 static const struct seq_operations kernfs_seq_ops = {
@@ -131,7 +167,7 @@ static const struct seq_operations kernfs_seq_ops = {
  * it difficult to use seq_file.  Implement simplistic custom buffering for
  * bin files.
  */
-static ssize_t kernfs_file_direct_read(struct sysfs_open_file *of,
+static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
                                       char __user *user_buf, size_t count,
                                       loff_t *ppos)
 {
@@ -148,19 +184,19 @@ static ssize_t kernfs_file_direct_read(struct sysfs_open_file *of,
         * the ops aren't called concurrently for the same open file.
         */
        mutex_lock(&of->mutex);
-       if (!sysfs_get_active(of->sd)) {
+       if (!kernfs_get_active(of->kn)) {
                len = -ENODEV;
                mutex_unlock(&of->mutex);
                goto out_free;
        }
 
-       ops = kernfs_ops(of->sd);
+       ops = kernfs_ops(of->kn);
        if (ops->read)
                len = ops->read(of, buf, len, *ppos);
        else
                len = -EINVAL;
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
        mutex_unlock(&of->mutex);
 
        if (len < 0)
@@ -179,25 +215,25 @@ static ssize_t kernfs_file_direct_read(struct sysfs_open_file *of,
 }
 
 /**
- * kernfs_file_read - kernfs vfs read callback
+ * kernfs_fop_read - kernfs vfs read callback
  * @file: file pointer
  * @user_buf: data to write
  * @count: number of bytes
  * @ppos: starting offset
  */
-static ssize_t kernfs_file_read(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos)
+static ssize_t kernfs_fop_read(struct file *file, char __user *user_buf,
+                              size_t count, loff_t *ppos)
 {
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
 
-       if (of->sd->s_flags & SYSFS_FLAG_HAS_SEQ_SHOW)
+       if (of->kn->flags & KERNFS_HAS_SEQ_SHOW)
                return seq_read(file, user_buf, count, ppos);
        else
                return kernfs_file_direct_read(of, user_buf, count, ppos);
 }
 
 /**
- * kernfs_file_write - kernfs vfs write callback
+ * kernfs_fop_write - kernfs vfs write callback
  * @file: file pointer
  * @user_buf: data to write
  * @count: number of bytes
@@ -212,10 +248,10 @@ static ssize_t kernfs_file_read(struct file *file, char __user *user_buf,
  * modify only the the value you're changing, then write entire buffer
  * back.
  */
-static ssize_t kernfs_file_write(struct file *file, const char __user *user_buf,
-                                size_t count, loff_t *ppos)
+static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
+                               size_t count, loff_t *ppos)
 {
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
        ssize_t len = min_t(size_t, count, PAGE_SIZE);
        const struct kernfs_ops *ops;
        char *buf;
@@ -235,19 +271,19 @@ static ssize_t kernfs_file_write(struct file *file, const char __user *user_buf,
         * the ops aren't called concurrently for the same open file.
         */
        mutex_lock(&of->mutex);
-       if (!sysfs_get_active(of->sd)) {
+       if (!kernfs_get_active(of->kn)) {
                mutex_unlock(&of->mutex);
                len = -ENODEV;
                goto out_free;
        }
 
-       ops = kernfs_ops(of->sd);
+       ops = kernfs_ops(of->kn);
        if (ops->write)
                len = ops->write(of, buf, len, *ppos);
        else
                len = -EINVAL;
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
        mutex_unlock(&of->mutex);
 
        if (len > 0)
@@ -260,37 +296,37 @@ out_free:
 static void kernfs_vma_open(struct vm_area_struct *vma)
 {
        struct file *file = vma->vm_file;
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
 
        if (!of->vm_ops)
                return;
 
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                return;
 
        if (of->vm_ops->open)
                of->vm_ops->open(vma);
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
 }
 
 static int kernfs_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct file *file = vma->vm_file;
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
        int ret;
 
        if (!of->vm_ops)
                return VM_FAULT_SIGBUS;
 
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                return VM_FAULT_SIGBUS;
 
        ret = VM_FAULT_SIGBUS;
        if (of->vm_ops->fault)
                ret = of->vm_ops->fault(vma, vmf);
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
        return ret;
 }
 
@@ -298,13 +334,13 @@ static int kernfs_vma_page_mkwrite(struct vm_area_struct *vma,
                                   struct vm_fault *vmf)
 {
        struct file *file = vma->vm_file;
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
        int ret;
 
        if (!of->vm_ops)
                return VM_FAULT_SIGBUS;
 
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                return VM_FAULT_SIGBUS;
 
        ret = 0;
@@ -313,7 +349,7 @@ static int kernfs_vma_page_mkwrite(struct vm_area_struct *vma,
        else
                file_update_time(file);
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
        return ret;
 }
 
@@ -321,20 +357,20 @@ static int kernfs_vma_access(struct vm_area_struct *vma, unsigned long addr,
                             void *buf, int len, int write)
 {
        struct file *file = vma->vm_file;
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
        int ret;
 
        if (!of->vm_ops)
                return -EINVAL;
 
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                return -EINVAL;
 
        ret = -EINVAL;
        if (of->vm_ops->access)
                ret = of->vm_ops->access(vma, addr, buf, len, write);
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
        return ret;
 }
 
@@ -343,20 +379,20 @@ static int kernfs_vma_set_policy(struct vm_area_struct *vma,
                                 struct mempolicy *new)
 {
        struct file *file = vma->vm_file;
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
        int ret;
 
        if (!of->vm_ops)
                return 0;
 
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                return -EINVAL;
 
        ret = 0;
        if (of->vm_ops->set_policy)
                ret = of->vm_ops->set_policy(vma, new);
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
        return ret;
 }
 
@@ -364,20 +400,20 @@ static struct mempolicy *kernfs_vma_get_policy(struct vm_area_struct *vma,
                                               unsigned long addr)
 {
        struct file *file = vma->vm_file;
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
        struct mempolicy *pol;
 
        if (!of->vm_ops)
                return vma->vm_policy;
 
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                return vma->vm_policy;
 
        pol = vma->vm_policy;
        if (of->vm_ops->get_policy)
                pol = of->vm_ops->get_policy(vma, addr);
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
        return pol;
 }
 
@@ -386,20 +422,20 @@ static int kernfs_vma_migrate(struct vm_area_struct *vma,
                              unsigned long flags)
 {
        struct file *file = vma->vm_file;
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
        int ret;
 
        if (!of->vm_ops)
                return 0;
 
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                return 0;
 
        ret = 0;
        if (of->vm_ops->migrate)
                ret = of->vm_ops->migrate(vma, from, to, flags);
 
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
        return ret;
 }
 #endif
@@ -416,23 +452,30 @@ static const struct vm_operations_struct kernfs_vm_ops = {
 #endif
 };
 
-static int kernfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct sysfs_open_file *of = sysfs_of(file);
+       struct kernfs_open_file *of = kernfs_of(file);
        const struct kernfs_ops *ops;
        int rc;
 
+       /*
+        * mmap path and of->mutex are prone to triggering spurious lockdep
+        * warnings and we don't want to add spurious locking dependency
+        * between the two.  Check whether mmap is actually implemented
+        * without grabbing @of->mutex by testing HAS_MMAP flag.  See the
+        * comment in kernfs_file_open() for more details.
+        */
+       if (!(of->kn->flags & KERNFS_HAS_MMAP))
+               return -ENODEV;
+
        mutex_lock(&of->mutex);
 
        rc = -ENODEV;
-       if (!sysfs_get_active(of->sd))
+       if (!kernfs_get_active(of->kn))
                goto out_unlock;
 
-       ops = kernfs_ops(of->sd);
-       if (ops->mmap)
-               rc = ops->mmap(of, vma);
-       if (rc)
-               goto out_put;
+       ops = kernfs_ops(of->kn);
+       rc = ops->mmap(of, vma);
 
        /*
         * PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup()
@@ -459,7 +502,7 @@ static int kernfs_file_mmap(struct file *file, struct vm_area_struct *vma)
        of->vm_ops = vma->vm_ops;
        vma->vm_ops = &kernfs_vm_ops;
 out_put:
-       sysfs_put_active(of->sd);
+       kernfs_put_active(of->kn);
 out_unlock:
        mutex_unlock(&of->mutex);
 
@@ -467,12 +510,12 @@ out_unlock:
 }
 
 /**
- *     sysfs_get_open_dirent - get or create sysfs_open_dirent
- *     @sd: target sysfs_dirent
- *     @of: sysfs_open_file for this instance of open
+ *     kernfs_get_open_node - get or create kernfs_open_node
+ *     @kn: target kernfs_node
+ *     @of: kernfs_open_file for this instance of open
  *
- *     If @sd->s_attr.open exists, increment its reference count;
- *     otherwise, create one.  @of is chained to the files list.
+ *     If @kn->attr.open exists, increment its reference count; otherwise,
+ *     create one.  @of is chained to the files list.
  *
  *     LOCKING:
  *     Kernel thread context (may sleep).
@@ -480,92 +523,92 @@ out_unlock:
  *     RETURNS:
  *     0 on success, -errno on failure.
  */
-static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
-                                struct sysfs_open_file *of)
+static int kernfs_get_open_node(struct kernfs_node *kn,
+                               struct kernfs_open_file *of)
 {
-       struct sysfs_open_dirent *od, *new_od = NULL;
+       struct kernfs_open_node *on, *new_on = NULL;
 
  retry:
-       mutex_lock(&sysfs_open_file_mutex);
-       spin_lock_irq(&sysfs_open_dirent_lock);
+       mutex_lock(&kernfs_open_file_mutex);
+       spin_lock_irq(&kernfs_open_node_lock);
 
-       if (!sd->s_attr.open && new_od) {
-               sd->s_attr.open = new_od;
-               new_od = NULL;
+       if (!kn->attr.open && new_on) {
+               kn->attr.open = new_on;
+               new_on = NULL;
        }
 
-       od = sd->s_attr.open;
-       if (od) {
-               atomic_inc(&od->refcnt);
-               list_add_tail(&of->list, &od->files);
+       on = kn->attr.open;
+       if (on) {
+               atomic_inc(&on->refcnt);
+               list_add_tail(&of->list, &on->files);
        }
 
-       spin_unlock_irq(&sysfs_open_dirent_lock);
-       mutex_unlock(&sysfs_open_file_mutex);
+       spin_unlock_irq(&kernfs_open_node_lock);
+       mutex_unlock(&kernfs_open_file_mutex);
 
-       if (od) {
-               kfree(new_od);
+       if (on) {
+               kfree(new_on);
                return 0;
        }
 
        /* not there, initialize a new one and retry */
-       new_od = kmalloc(sizeof(*new_od), GFP_KERNEL);
-       if (!new_od)
+       new_on = kmalloc(sizeof(*new_on), GFP_KERNEL);
+       if (!new_on)
                return -ENOMEM;
 
-       atomic_set(&new_od->refcnt, 0);
-       atomic_set(&new_od->event, 1);
-       init_waitqueue_head(&new_od->poll);
-       INIT_LIST_HEAD(&new_od->files);
+       atomic_set(&new_on->refcnt, 0);
+       atomic_set(&new_on->event, 1);
+       init_waitqueue_head(&new_on->poll);
+       INIT_LIST_HEAD(&new_on->files);
        goto retry;
 }
 
 /**
- *     sysfs_put_open_dirent - put sysfs_open_dirent
- *     @sd: target sysfs_dirent
- *     @of: associated sysfs_open_file
+ *     kernfs_put_open_node - put kernfs_open_node
+ *     @kn: target kernfs_nodet
+ *     @of: associated kernfs_open_file
  *
- *     Put @sd->s_attr.open and unlink @of from the files list.  If
+ *     Put @kn->attr.open and unlink @of from the files list.  If
  *     reference count reaches zero, disassociate and free it.
  *
  *     LOCKING:
  *     None.
  */
-static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
-                                 struct sysfs_open_file *of)
+static void kernfs_put_open_node(struct kernfs_node *kn,
+                                struct kernfs_open_file *of)
 {
-       struct sysfs_open_dirent *od = sd->s_attr.open;
+       struct kernfs_open_node *on = kn->attr.open;
        unsigned long flags;
 
-       mutex_lock(&sysfs_open_file_mutex);
-       spin_lock_irqsave(&sysfs_open_dirent_lock, flags);
+       mutex_lock(&kernfs_open_file_mutex);
+       spin_lock_irqsave(&kernfs_open_node_lock, flags);
 
        if (of)
                list_del(&of->list);
 
-       if (atomic_dec_and_test(&od->refcnt))
-               sd->s_attr.open = NULL;
+       if (atomic_dec_and_test(&on->refcnt))
+               kn->attr.open = NULL;
        else
-               od = NULL;
+               on = NULL;
 
-       spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags);
-       mutex_unlock(&sysfs_open_file_mutex);
+       spin_unlock_irqrestore(&kernfs_open_node_lock, flags);
+       mutex_unlock(&kernfs_open_file_mutex);
 
-       kfree(od);
+       kfree(on);
 }
 
-static int kernfs_file_open(struct inode *inode, struct file *file)
+static int kernfs_fop_open(struct inode *inode, struct file *file)
 {
-       struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+       struct kernfs_node *kn = file->f_path.dentry->d_fsdata;
        const struct kernfs_ops *ops;
-       struct sysfs_open_file *of;
+       struct kernfs_open_file *of;
        bool has_read, has_write, has_mmap;
        int error = -EACCES;
 
-       if (!sysfs_get_active(attr_sd))
+       if (!kernfs_get_active(kn))
                return -ENODEV;
 
-       ops = kernfs_ops(attr_sd);
+       ops = kernfs_ops(kn);
 
        has_read = ops->seq_show || ops->read || ops->mmap;
        has_write = ops->write || ops->mmap;
@@ -580,9 +623,9 @@ static int kernfs_file_open(struct inode *inode, struct file *file)
            (!(inode->i_mode & S_IRUGO) || !has_read))
                goto err_out;
 
-       /* allocate a sysfs_open_file for the file */
+       /* allocate a kernfs_open_file for the file */
        error = -ENOMEM;
-       of = kzalloc(sizeof(struct sysfs_open_file), GFP_KERNEL);
+       of = kzalloc(sizeof(struct kernfs_open_file), GFP_KERNEL);
        if (!of)
                goto err_out;
 
@@ -597,13 +640,16 @@ static int kernfs_file_open(struct inode *inode, struct file *file)
         * happen on the same file.  At this point, we can't easily give
         * each file a separate locking class.  Let's differentiate on
         * whether the file has mmap or not for now.
+        *
+        * Both paths of the branch look the same.  They're supposed to
+        * look that way and give @of->mutex different static lockdep keys.
         */
        if (has_mmap)
                mutex_init(&of->mutex);
        else
                mutex_init(&of->mutex);
 
-       of->sd = attr_sd;
+       of->kn = kn;
        of->file = file;
 
        /*
@@ -624,13 +670,13 @@ static int kernfs_file_open(struct inode *inode, struct file *file)
        if (file->f_mode & FMODE_WRITE)
                file->f_mode |= FMODE_PWRITE;
 
-       /* make sure we have open dirent struct */
-       error = sysfs_get_open_dirent(attr_sd, of);
+       /* make sure we have open node struct */
+       error = kernfs_get_open_node(kn, of);
        if (error)
                goto err_close;
 
        /* open succeeded, put active references */
-       sysfs_put_active(attr_sd);
+       kernfs_put_active(kn);
        return 0;
 
 err_close:
@@ -638,49 +684,50 @@ err_close:
 err_free:
        kfree(of);
 err_out:
-       sysfs_put_active(attr_sd);
+       kernfs_put_active(kn);
        return error;
 }
 
-static int kernfs_file_release(struct inode *inode, struct file *filp)
+static int kernfs_fop_release(struct inode *inode, struct file *filp)
 {
-       struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata;
-       struct sysfs_open_file *of = sysfs_of(filp);
+       struct kernfs_node *kn = filp->f_path.dentry->d_fsdata;
+       struct kernfs_open_file *of = kernfs_of(filp);
 
-       sysfs_put_open_dirent(sd, of);
+       kernfs_put_open_node(kn, of);
        seq_release(inode, filp);
        kfree(of);
 
        return 0;
 }
 
-void sysfs_unmap_bin_file(struct sysfs_dirent *sd)
+void kernfs_unmap_bin_file(struct kernfs_node *kn)
 {
-       struct sysfs_open_dirent *od;
-       struct sysfs_open_file *of;
+       struct kernfs_open_node *on;
+       struct kernfs_open_file *of;
 
-       if (!(sd->s_flags & SYSFS_FLAG_HAS_MMAP))
+       if (!(kn->flags & KERNFS_HAS_MMAP))
                return;
 
-       spin_lock_irq(&sysfs_open_dirent_lock);
-       od = sd->s_attr.open;
-       if (od)
-               atomic_inc(&od->refcnt);
-       spin_unlock_irq(&sysfs_open_dirent_lock);
-       if (!od)
+       spin_lock_irq(&kernfs_open_node_lock);
+       on = kn->attr.open;
+       if (on)
+               atomic_inc(&on->refcnt);
+       spin_unlock_irq(&kernfs_open_node_lock);
+       if (!on)
                return;
 
-       mutex_lock(&sysfs_open_file_mutex);
-       list_for_each_entry(of, &od->files, list) {
+       mutex_lock(&kernfs_open_file_mutex);
+       list_for_each_entry(of, &on->files, list) {
                struct inode *inode = file_inode(of->file);
                unmap_mapping_range(inode->i_mapping, 0, 0, 1);
        }
-       mutex_unlock(&sysfs_open_file_mutex);
+       mutex_unlock(&kernfs_open_file_mutex);
 
-       sysfs_put_open_dirent(sd, NULL);
+       kernfs_put_open_node(kn, NULL);
 }
 
-/* Sysfs attribute files are pollable.  The idea is that you read
+/*
+ * Kernfs attribute files are pollable.  The idea is that you read
  * the content and then you use 'poll' or 'select' to wait for
  * the content to change.  When the content changes (assuming the
  * manager for the kobject supports notification), poll will
@@ -693,21 +740,21 @@ void sysfs_unmap_bin_file(struct sysfs_dirent *sd)
  * to see if it supports poll (Neither 'poll' nor 'select' return
  * an appropriate error code).  When in doubt, set a suitable timeout value.
  */
-static unsigned int kernfs_file_poll(struct file *filp, poll_table *wait)
+static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
 {
-       struct sysfs_open_file *of = sysfs_of(filp);
-       struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
-       struct sysfs_open_dirent *od = attr_sd->s_attr.open;
+       struct kernfs_open_file *of = kernfs_of(filp);
+       struct kernfs_node *kn = filp->f_path.dentry->d_fsdata;
+       struct kernfs_open_node *on = kn->attr.open;
 
        /* need parent for the kobj, grab both */
-       if (!sysfs_get_active(attr_sd))
+       if (!kernfs_get_active(kn))
                goto trigger;
 
-       poll_wait(filp, &od->poll, wait);
+       poll_wait(filp, &on->poll, wait);
 
-       sysfs_put_active(attr_sd);
+       kernfs_put_active(kn);
 
-       if (of->event != atomic_read(&od->event))
+       if (of->event != atomic_read(&on->event))
                goto trigger;
 
        return DEFAULT_POLLMASK;
@@ -718,41 +765,41 @@ static unsigned int kernfs_file_poll(struct file *filp, poll_table *wait)
 
 /**
  * kernfs_notify - notify a kernfs file
- * @sd: file to notify
+ * @kn: file to notify
  *
- * Notify @sd such that poll(2) on @sd wakes up.
+ * Notify @kn such that poll(2) on @kn wakes up.
  */
-void kernfs_notify(struct sysfs_dirent *sd)
+void kernfs_notify(struct kernfs_node *kn)
 {
-       struct sysfs_open_dirent *od;
+       struct kernfs_open_node *on;
        unsigned long flags;
 
-       spin_lock_irqsave(&sysfs_open_dirent_lock, flags);
+       spin_lock_irqsave(&kernfs_open_node_lock, flags);
 
-       if (!WARN_ON(sysfs_type(sd) != SYSFS_KOBJ_ATTR)) {
-               od = sd->s_attr.open;
-               if (od) {
-                       atomic_inc(&od->event);
-                       wake_up_interruptible(&od->poll);
+       if (!WARN_ON(kernfs_type(kn) != KERNFS_FILE)) {
+               on = kn->attr.open;
+               if (on) {
+                       atomic_inc(&on->event);
+                       wake_up_interruptible(&on->poll);
                }
        }
 
-       spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags);
+       spin_unlock_irqrestore(&kernfs_open_node_lock, flags);
 }
 EXPORT_SYMBOL_GPL(kernfs_notify);
 
-const struct file_operations kernfs_file_operations = {
-       .read           = kernfs_file_read,
-       .write          = kernfs_file_write,
+const struct file_operations kernfs_file_fops = {
+       .read           = kernfs_fop_read,
+       .write          = kernfs_fop_write,
        .llseek         = generic_file_llseek,
-       .mmap           = kernfs_file_mmap,
-       .open           = kernfs_file_open,
-       .release        = kernfs_file_release,
-       .poll           = kernfs_file_poll,
+       .mmap           = kernfs_fop_mmap,
+       .open           = kernfs_fop_open,
+       .release        = kernfs_fop_release,
+       .poll           = kernfs_fop_poll,
 };
 
 /**
- * kernfs_create_file_ns_key - create a file
+ * __kernfs_create_file - kernfs internal function to create a file
  * @parent: directory to create the file in
  * @name: name of the file
  * @mode: mode of the file
@@ -760,55 +807,66 @@ const struct file_operations kernfs_file_operations = {
  * @ops: kernfs operations for the file
  * @priv: private data for the file
  * @ns: optional namespace tag of the file
+ * @static_name: don't copy file name
  * @key: lockdep key for the file's active_ref, %NULL to disable lockdep
  *
  * Returns the created node on success, ERR_PTR() value on error.
  */
-struct sysfs_dirent *kernfs_create_file_ns_key(struct sysfs_dirent *parent,
-                                              const char *name,
-                                              umode_t mode, loff_t size,
-                                              const struct kernfs_ops *ops,
-                                              void *priv, const void *ns,
-                                              struct lock_class_key *key)
+struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
+                                        const char *name,
+                                        umode_t mode, loff_t size,
+                                        const struct kernfs_ops *ops,
+                                        void *priv, const void *ns,
+                                        bool name_is_static,
+                                        struct lock_class_key *key)
 {
-       struct sysfs_addrm_cxt acxt;
-       struct sysfs_dirent *sd;
+       struct kernfs_addrm_cxt acxt;
+       struct kernfs_node *kn;
+       unsigned flags;
        int rc;
 
-       sd = sysfs_new_dirent(kernfs_root(parent), name,
-                             (mode & S_IALLUGO) | S_IFREG, SYSFS_KOBJ_ATTR);
-       if (!sd)
+       flags = KERNFS_FILE;
+       if (name_is_static)
+               flags |= KERNFS_STATIC_NAME;
+
+       kn = kernfs_new_node(kernfs_root(parent), name,
+                            (mode & S_IALLUGO) | S_IFREG, flags);
+       if (!kn)
                return ERR_PTR(-ENOMEM);
 
-       sd->s_attr.ops = ops;
-       sd->s_attr.size = size;
-       sd->s_ns = ns;
-       sd->priv = priv;
+       kn->attr.ops = ops;
+       kn->attr.size = size;
+       kn->ns = ns;
+       kn->priv = priv;
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
        if (key) {
-               lockdep_init_map(&sd->dep_map, "s_active", key, 0);
-               sd->s_flags |= SYSFS_FLAG_LOCKDEP;
+               lockdep_init_map(&kn->dep_map, "s_active", key, 0);
+               kn->flags |= KERNFS_LOCKDEP;
        }
 #endif
 
        /*
-        * sd->s_attr.ops is accesible only while holding active ref.  We
+        * kn->attr.ops is accesible only while holding active ref.  We
         * need to know whether some ops are implemented outside active
         * ref.  Cache their existence in flags.
         */
        if (ops->seq_show)
-               sd->s_flags |= SYSFS_FLAG_HAS_SEQ_SHOW;
+               kn->flags |= KERNFS_HAS_SEQ_SHOW;
        if (ops->mmap)
-               sd->s_flags |= SYSFS_FLAG_HAS_MMAP;
-
-       sysfs_addrm_start(&acxt);
-       rc = sysfs_add_one(&acxt, sd, parent);
-       sysfs_addrm_finish(&acxt);
+               kn->flags |= KERNFS_HAS_MMAP;
+
+       rc = -ENOENT;
+       if (kernfs_get_active(parent)) {
+               kernfs_addrm_start(&acxt);
+               rc = kernfs_add_one(&acxt, kn, parent);
+               kernfs_addrm_finish(&acxt);
+               kernfs_put_active(parent);
+       }
 
        if (rc) {
-               kernfs_put(sd);
+               kernfs_put(kn);
                return ERR_PTR(rc);
        }
-       return sd;
+       return kn;
 }
This page took 0.04015 seconds and 5 git commands to generate.