get rid of autofs_getpath()
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 8 Mar 2021 15:16:16 +0000 (10:16 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 21 Mar 2021 15:44:02 +0000 (11:44 -0400)
allow wq->name.name to point not at the beginning of the object containing
the string, with wq->offset telling how far into it we are.  Then we can
bloody well just use dentry_path_raw() instead of autofs_getpath() -
the only real difference is that dentry_path_raw() puts the result into
the end of buffer and returns where it starts.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/autofs/autofs_i.h
fs/autofs/waitq.c

index 054f97b..918826e 100644 (file)
@@ -87,6 +87,7 @@ struct autofs_wait_queue {
        autofs_wqt_t wait_queue_token;
        /* We use the following to see what we are waiting for */
        struct qstr name;
+       u32 offset;
        u32 dev;
        u64 ino;
        kuid_t uid;
index 5ced859..16b5fca 100644 (file)
@@ -30,7 +30,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
        while (wq) {
                nwq = wq->next;
                wq->status = -ENOENT; /* Magic is gone - report failure */
-               kfree(wq->name.name);
+               kfree(wq->name.name - wq->offset);
                wq->name.name = NULL;
                wq->wait_ctr--;
                wake_up_interruptible(&wq->queue);
@@ -175,51 +175,6 @@ static void autofs_notify_daemon(struct autofs_sb_info *sbi,
        fput(pipe);
 }
 
-static int autofs_getpath(struct autofs_sb_info *sbi,
-                         struct dentry *dentry, char *name)
-{
-       struct dentry *root = sbi->sb->s_root;
-       struct dentry *tmp;
-       char *buf;
-       char *p;
-       int len;
-       unsigned seq;
-
-rename_retry:
-       buf = name;
-       len = 0;
-
-       seq = read_seqbegin(&rename_lock);
-       rcu_read_lock();
-       spin_lock(&sbi->fs_lock);
-       for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent)
-               len += tmp->d_name.len + 1;
-
-       if (!len || --len > NAME_MAX) {
-               spin_unlock(&sbi->fs_lock);
-               rcu_read_unlock();
-               if (read_seqretry(&rename_lock, seq))
-                       goto rename_retry;
-               return 0;
-       }
-
-       *(buf + len) = '\0';
-       p = buf + len - dentry->d_name.len;
-       strncpy(p, dentry->d_name.name, dentry->d_name.len);
-
-       for (tmp = dentry->d_parent; tmp != root ; tmp = tmp->d_parent) {
-               *(--p) = '/';
-               p -= tmp->d_name.len;
-               strncpy(p, tmp->d_name.name, tmp->d_name.len);
-       }
-       spin_unlock(&sbi->fs_lock);
-       rcu_read_unlock();
-       if (read_seqretry(&rename_lock, seq))
-               goto rename_retry;
-
-       return len;
-}
-
 static struct autofs_wait_queue *
 autofs_find_wait(struct autofs_sb_info *sbi, const struct qstr *qstr)
 {
@@ -352,6 +307,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
        struct qstr qstr;
        char *name;
        int status, ret, type;
+       unsigned int offset = 0;
        pid_t pid;
        pid_t tgid;
 
@@ -389,20 +345,23 @@ int autofs_wait(struct autofs_sb_info *sbi,
                return -ENOMEM;
 
        /* If this is a direct mount request create a dummy name */
-       if (IS_ROOT(dentry) && autofs_type_trigger(sbi->type))
+       if (IS_ROOT(dentry) && autofs_type_trigger(sbi->type)) {
+               qstr.name = name;
                qstr.len = sprintf(name, "%p", dentry);
-       else {
-               qstr.len = autofs_getpath(sbi, dentry, name);
-               if (!qstr.len) {
+       else {
+               char *p = dentry_path_raw(dentry, name, NAME_MAX);
+               if (IS_ERR(p)) {
                        kfree(name);
                        return -ENOENT;
                }
+               qstr.name = ++p; // skip the leading slash
+               qstr.len = strlen(p);
+               offset = p - name;
        }
-       qstr.name = name;
        qstr.hash = full_name_hash(dentry, name, qstr.len);
 
        if (mutex_lock_interruptible(&sbi->wq_mutex)) {
-               kfree(qstr.name);
+               kfree(name);
                return -EINTR;
        }
 
@@ -410,7 +369,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
        if (ret <= 0) {
                if (ret != -EINTR)
                        mutex_unlock(&sbi->wq_mutex);
-               kfree(qstr.name);
+               kfree(name);
                return ret;
        }
 
@@ -418,7 +377,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
                /* Create a new wait queue */
                wq = kmalloc(sizeof(struct autofs_wait_queue), GFP_KERNEL);
                if (!wq) {
-                       kfree(qstr.name);
+                       kfree(name);
                        mutex_unlock(&sbi->wq_mutex);
                        return -ENOMEM;
                }
@@ -430,6 +389,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
                sbi->queues = wq;
                init_waitqueue_head(&wq->queue);
                memcpy(&wq->name, &qstr, sizeof(struct qstr));
+               wq->offset = offset;
                wq->dev = autofs_get_dev(sbi);
                wq->ino = autofs_get_ino(sbi);
                wq->uid = current_uid();
@@ -469,7 +429,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
                         (unsigned long) wq->wait_queue_token, wq->name.len,
                         wq->name.name, notify);
                mutex_unlock(&sbi->wq_mutex);
-               kfree(qstr.name);
+               kfree(name);
        }
 
        /*
@@ -540,7 +500,7 @@ int autofs_wait_release(struct autofs_sb_info *sbi,
        }
 
        *wql = wq->next;        /* Unlink from chain */
-       kfree(wq->name.name);
+       kfree(wq->name.name - wq->offset);
        wq->name.name = NULL;   /* Do not wait on this queue */
        wq->status = status;
        wake_up(&wq->queue);