^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* -*- mode: c; c-basic-offset: 8; -*-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * vim: noexpandtab sw=8 ts=8 sts=0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * symlink.c - operations for configfs symlinks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on sysfs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * configfs Copyright (C) 2005 Oracle. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/configfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "configfs_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* Protects attachments of new symlinks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) DEFINE_MUTEX(configfs_symlink_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int item_depth(struct config_item * item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct config_item * p = item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int depth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) do { depth++; } while ((p = p->ci_parent) && !configfs_is_root(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int item_path_length(struct config_item * item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct config_item * p = item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) length += strlen(config_item_name(p)) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) p = p->ci_parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) } while (p && !configfs_is_root(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static void fill_item_path(struct config_item * item, char * buffer, int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct config_item * p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) --length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) for (p = item; p && !configfs_is_root(p); p = p->ci_parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int cur = strlen(config_item_name(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* back up enough to print this bus id with '/' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) length -= cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) memcpy(buffer + length, config_item_name(p), cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *(buffer + --length) = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int configfs_get_target_path(struct config_item *item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct config_item *target, char *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int depth, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) depth = item_depth(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) size = item_path_length(target) + depth * 3 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (size > PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) pr_debug("%s: depth = %d, size = %d\n", __func__, depth, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) for (s = path; depth--; s += 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) strcpy(s,"../");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) fill_item_path(target, path, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pr_debug("%s: path = '%s'\n", __func__, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int create_link(struct config_item *parent_item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct config_item *item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct configfs_dirent *target_sd = item->ci_dentry->d_fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) char *body;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (!configfs_dirent_is_ready(target_sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) body = kzalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!body)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) configfs_get(target_sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) spin_lock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) spin_unlock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) configfs_put(target_sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) kfree(body);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) target_sd->s_links++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) spin_unlock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ret = configfs_get_target_path(parent_item, item, body);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ret = configfs_create_link(target_sd, parent_item->ci_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dentry, body);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) spin_lock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) target_sd->s_links--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) spin_unlock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) configfs_put(target_sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) kfree(body);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int get_target(const char *symname, struct path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct config_item **target, struct super_block *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ret = kern_path(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (path->dentry->d_sb == sb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *target = configfs_get_config_item(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (!*target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) path_put(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) path_put(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct configfs_dirent *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct config_item *parent_item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct config_item *target_item = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) const struct config_item_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) sd = dentry->d_parent->d_fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Fake invisibility if dir belongs to a group/default groups hierarchy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * being attached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!configfs_dirent_is_ready(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) parent_item = configfs_get_config_item(dentry->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) type = parent_item->ci_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (!type || !type->ct_item_ops ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) !type->ct_item_ops->allow_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * This is really sick. What they wanted was a hybrid of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * link(2) and symlink(2) - they wanted the target resolved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * at syscall time (as link(2) would've done), be a directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * (which link(2) would've refused to do) *AND* be a deep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * fucking magic, making the target busy from rmdir POV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * symlink(2) is nothing of that sort, and the locking it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * gets matches the normal symlink(2) semantics. Without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * attempts to resolve the target (which might very well
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * not even exist yet) done prior to locking the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * directory. This perversion, OTOH, needs to resolve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * the target, which would lead to obvious deadlocks if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * attempted with any directories locked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * Unfortunately, that garbage is userland ABI and we should've
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * said "no" back in 2005. Too late now, so we get to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * play very ugly games with locking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * Try *ANYTHING* of that sort in new code, and you will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * really regret it. Just ask yourself - what could a BOFH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * do to me and do I want to find it out first-hand?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * AV, a thoroughly annoyed bastard.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) inode_unlock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ret = get_target(symname, &path, &target_item, dentry->d_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) inode_lock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (dentry->d_inode || d_unhashed(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) ret = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ret = inode_permission(dir, MAY_WRITE | MAY_EXEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = type->ct_item_ops->allow_link(parent_item, target_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) mutex_lock(&configfs_symlink_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ret = create_link(parent_item, target_item, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) mutex_unlock(&configfs_symlink_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (ret && type->ct_item_ops->drop_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) type->ct_item_ops->drop_link(parent_item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) target_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) config_item_put(target_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) path_put(&path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) out_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) config_item_put(parent_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int configfs_unlink(struct inode *dir, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct configfs_dirent *sd = dentry->d_fsdata, *target_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct config_item *parent_item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) const struct config_item_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ret = -EPERM; /* What lack-of-symlink returns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!(sd->s_type & CONFIGFS_ITEM_LINK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) target_sd = sd->s_element;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) parent_item = configfs_get_config_item(dentry->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) type = parent_item->ci_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) spin_lock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) list_del_init(&sd->s_sibling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) spin_unlock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) configfs_drop_dentry(sd, dentry->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) configfs_put(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * drop_link() must be called before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * decrementing target's ->s_links, so that the order of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * drop_link(this, target) and drop_item(target) is preserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (type && type->ct_item_ops &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) type->ct_item_ops->drop_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) type->ct_item_ops->drop_link(parent_item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) target_sd->s_element);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) spin_lock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) target_sd->s_links--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) spin_unlock(&configfs_dirent_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) configfs_put(target_sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) config_item_put(parent_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) const struct inode_operations configfs_symlink_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .get_link = simple_get_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .setattr = configfs_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)