1b8441ed2STejun Heo /* 2b8441ed2STejun Heo * fs/kernfs/dir.c - kernfs directory implementation 3b8441ed2STejun Heo * 4b8441ed2STejun Heo * Copyright (c) 2001-3 Patrick Mochel 5b8441ed2STejun Heo * Copyright (c) 2007 SUSE Linux Products GmbH 6b8441ed2STejun Heo * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org> 7b8441ed2STejun Heo * 8b8441ed2STejun Heo * This file is released under the GPLv2. 9b8441ed2STejun Heo */ 10fd7b9f7bSTejun Heo 11ea1c472dSTejun Heo #include <linux/sched.h> 12fd7b9f7bSTejun Heo #include <linux/fs.h> 13fd7b9f7bSTejun Heo #include <linux/namei.h> 14fd7b9f7bSTejun Heo #include <linux/idr.h> 15fd7b9f7bSTejun Heo #include <linux/slab.h> 16fd7b9f7bSTejun Heo #include <linux/security.h> 17fd7b9f7bSTejun Heo #include <linux/hash.h> 18fd7b9f7bSTejun Heo 19fd7b9f7bSTejun Heo #include "kernfs-internal.h" 20fd7b9f7bSTejun Heo 21a797bfc3STejun Heo DEFINE_MUTEX(kernfs_mutex); 22fd7b9f7bSTejun Heo 23adc5e8b5STejun Heo #define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb) 24fd7b9f7bSTejun Heo 25a69d001cSTejun Heo static bool kernfs_lockdep(struct kernfs_node *kn) 26a69d001cSTejun Heo { 27a69d001cSTejun Heo #ifdef CONFIG_DEBUG_LOCK_ALLOC 28a69d001cSTejun Heo return kn->flags & KERNFS_LOCKDEP; 29a69d001cSTejun Heo #else 30a69d001cSTejun Heo return false; 31a69d001cSTejun Heo #endif 32a69d001cSTejun Heo } 33a69d001cSTejun Heo 34fd7b9f7bSTejun Heo /** 35c637b8acSTejun Heo * kernfs_name_hash 36fd7b9f7bSTejun Heo * @name: Null terminated string to hash 37fd7b9f7bSTejun Heo * @ns: Namespace tag to hash 38fd7b9f7bSTejun Heo * 39fd7b9f7bSTejun Heo * Returns 31 bit hash of ns + name (so it fits in an off_t ) 40fd7b9f7bSTejun Heo */ 41c637b8acSTejun Heo static unsigned int kernfs_name_hash(const char *name, const void *ns) 42fd7b9f7bSTejun Heo { 43fd7b9f7bSTejun Heo unsigned long hash = init_name_hash(); 44fd7b9f7bSTejun Heo unsigned int len = strlen(name); 45fd7b9f7bSTejun Heo while (len--) 46fd7b9f7bSTejun Heo hash = partial_name_hash(*name++, hash); 47fd7b9f7bSTejun Heo hash = (end_name_hash(hash) ^ hash_ptr((void *)ns, 31)); 48fd7b9f7bSTejun Heo hash &= 0x7fffffffU; 49fd7b9f7bSTejun Heo /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */ 50fd7b9f7bSTejun Heo if (hash < 1) 51fd7b9f7bSTejun Heo hash += 2; 52fd7b9f7bSTejun Heo if (hash >= INT_MAX) 53fd7b9f7bSTejun Heo hash = INT_MAX - 1; 54fd7b9f7bSTejun Heo return hash; 55fd7b9f7bSTejun Heo } 56fd7b9f7bSTejun Heo 57c637b8acSTejun Heo static int kernfs_name_compare(unsigned int hash, const char *name, 58324a56e1STejun Heo const void *ns, const struct kernfs_node *kn) 59fd7b9f7bSTejun Heo { 60adc5e8b5STejun Heo if (hash != kn->hash) 61adc5e8b5STejun Heo return hash - kn->hash; 62adc5e8b5STejun Heo if (ns != kn->ns) 63adc5e8b5STejun Heo return ns - kn->ns; 64adc5e8b5STejun Heo return strcmp(name, kn->name); 65fd7b9f7bSTejun Heo } 66fd7b9f7bSTejun Heo 67c637b8acSTejun Heo static int kernfs_sd_compare(const struct kernfs_node *left, 68324a56e1STejun Heo const struct kernfs_node *right) 69fd7b9f7bSTejun Heo { 70c637b8acSTejun Heo return kernfs_name_compare(left->hash, left->name, left->ns, right); 71fd7b9f7bSTejun Heo } 72fd7b9f7bSTejun Heo 73fd7b9f7bSTejun Heo /** 74c637b8acSTejun Heo * kernfs_link_sibling - link kernfs_node into sibling rbtree 75324a56e1STejun Heo * @kn: kernfs_node of interest 76fd7b9f7bSTejun Heo * 77324a56e1STejun Heo * Link @kn into its sibling rbtree which starts from 78adc5e8b5STejun Heo * @kn->parent->dir.children. 79fd7b9f7bSTejun Heo * 80fd7b9f7bSTejun Heo * Locking: 81a797bfc3STejun Heo * mutex_lock(kernfs_mutex) 82fd7b9f7bSTejun Heo * 83fd7b9f7bSTejun Heo * RETURNS: 84fd7b9f7bSTejun Heo * 0 on susccess -EEXIST on failure. 85fd7b9f7bSTejun Heo */ 86c637b8acSTejun Heo static int kernfs_link_sibling(struct kernfs_node *kn) 87fd7b9f7bSTejun Heo { 88adc5e8b5STejun Heo struct rb_node **node = &kn->parent->dir.children.rb_node; 89fd7b9f7bSTejun Heo struct rb_node *parent = NULL; 90fd7b9f7bSTejun Heo 91df23fc39STejun Heo if (kernfs_type(kn) == KERNFS_DIR) 92adc5e8b5STejun Heo kn->parent->dir.subdirs++; 93fd7b9f7bSTejun Heo 94fd7b9f7bSTejun Heo while (*node) { 95324a56e1STejun Heo struct kernfs_node *pos; 96fd7b9f7bSTejun Heo int result; 97fd7b9f7bSTejun Heo 98324a56e1STejun Heo pos = rb_to_kn(*node); 99fd7b9f7bSTejun Heo parent = *node; 100c637b8acSTejun Heo result = kernfs_sd_compare(kn, pos); 101fd7b9f7bSTejun Heo if (result < 0) 102adc5e8b5STejun Heo node = &pos->rb.rb_left; 103fd7b9f7bSTejun Heo else if (result > 0) 104adc5e8b5STejun Heo node = &pos->rb.rb_right; 105fd7b9f7bSTejun Heo else 106fd7b9f7bSTejun Heo return -EEXIST; 107fd7b9f7bSTejun Heo } 108fd7b9f7bSTejun Heo /* add new node and rebalance the tree */ 109adc5e8b5STejun Heo rb_link_node(&kn->rb, parent, node); 110adc5e8b5STejun Heo rb_insert_color(&kn->rb, &kn->parent->dir.children); 111fd7b9f7bSTejun Heo return 0; 112fd7b9f7bSTejun Heo } 113fd7b9f7bSTejun Heo 114fd7b9f7bSTejun Heo /** 115c637b8acSTejun Heo * kernfs_unlink_sibling - unlink kernfs_node from sibling rbtree 116324a56e1STejun Heo * @kn: kernfs_node of interest 117fd7b9f7bSTejun Heo * 118324a56e1STejun Heo * Unlink @kn from its sibling rbtree which starts from 119adc5e8b5STejun Heo * kn->parent->dir.children. 120fd7b9f7bSTejun Heo * 121fd7b9f7bSTejun Heo * Locking: 122a797bfc3STejun Heo * mutex_lock(kernfs_mutex) 123fd7b9f7bSTejun Heo */ 124f601f9a2STejun Heo static bool kernfs_unlink_sibling(struct kernfs_node *kn) 125fd7b9f7bSTejun Heo { 126f601f9a2STejun Heo if (RB_EMPTY_NODE(&kn->rb)) 127f601f9a2STejun Heo return false; 128f601f9a2STejun Heo 129df23fc39STejun Heo if (kernfs_type(kn) == KERNFS_DIR) 130adc5e8b5STejun Heo kn->parent->dir.subdirs--; 131fd7b9f7bSTejun Heo 132adc5e8b5STejun Heo rb_erase(&kn->rb, &kn->parent->dir.children); 133ae34372eSTejun Heo RB_CLEAR_NODE(&kn->rb); 134f601f9a2STejun Heo return true; 135fd7b9f7bSTejun Heo } 136fd7b9f7bSTejun Heo 137fd7b9f7bSTejun Heo /** 138c637b8acSTejun Heo * kernfs_get_active - get an active reference to kernfs_node 139324a56e1STejun Heo * @kn: kernfs_node to get an active reference to 140fd7b9f7bSTejun Heo * 141324a56e1STejun Heo * Get an active reference of @kn. This function is noop if @kn 142fd7b9f7bSTejun Heo * is NULL. 143fd7b9f7bSTejun Heo * 144fd7b9f7bSTejun Heo * RETURNS: 145324a56e1STejun Heo * Pointer to @kn on success, NULL on failure. 146fd7b9f7bSTejun Heo */ 147c637b8acSTejun Heo struct kernfs_node *kernfs_get_active(struct kernfs_node *kn) 148fd7b9f7bSTejun Heo { 149324a56e1STejun Heo if (unlikely(!kn)) 150fd7b9f7bSTejun Heo return NULL; 151fd7b9f7bSTejun Heo 152f4b3e631SGreg Kroah-Hartman if (!atomic_inc_unless_negative(&kn->active)) 153f4b3e631SGreg Kroah-Hartman return NULL; 154f4b3e631SGreg Kroah-Hartman 155a69d001cSTejun Heo if (kernfs_lockdep(kn)) 156324a56e1STejun Heo rwsem_acquire_read(&kn->dep_map, 0, 1, _RET_IP_); 157324a56e1STejun Heo return kn; 158fd7b9f7bSTejun Heo } 159fd7b9f7bSTejun Heo 160fd7b9f7bSTejun Heo /** 161c637b8acSTejun Heo * kernfs_put_active - put an active reference to kernfs_node 162324a56e1STejun Heo * @kn: kernfs_node to put an active reference to 163fd7b9f7bSTejun Heo * 164324a56e1STejun Heo * Put an active reference to @kn. This function is noop if @kn 165fd7b9f7bSTejun Heo * is NULL. 166fd7b9f7bSTejun Heo */ 167c637b8acSTejun Heo void kernfs_put_active(struct kernfs_node *kn) 168fd7b9f7bSTejun Heo { 169ea1c472dSTejun Heo struct kernfs_root *root = kernfs_root(kn); 170fd7b9f7bSTejun Heo int v; 171fd7b9f7bSTejun Heo 172324a56e1STejun Heo if (unlikely(!kn)) 173fd7b9f7bSTejun Heo return; 174fd7b9f7bSTejun Heo 175a69d001cSTejun Heo if (kernfs_lockdep(kn)) 176324a56e1STejun Heo rwsem_release(&kn->dep_map, 1, _RET_IP_); 177adc5e8b5STejun Heo v = atomic_dec_return(&kn->active); 178df23fc39STejun Heo if (likely(v != KN_DEACTIVATED_BIAS)) 179fd7b9f7bSTejun Heo return; 180fd7b9f7bSTejun Heo 181ea1c472dSTejun Heo wake_up_all(&root->deactivate_waitq); 182fd7b9f7bSTejun Heo } 183fd7b9f7bSTejun Heo 184fd7b9f7bSTejun Heo /** 185ae34372eSTejun Heo * kernfs_drain - drain kernfs_node 186ae34372eSTejun Heo * @kn: kernfs_node to drain 187fd7b9f7bSTejun Heo * 18845a140e5STejun Heo * Drain existing usages of @kn. Mutiple removers may invoke this function 18945a140e5STejun Heo * concurrently on @kn and all will return after draining is complete. 19045a140e5STejun Heo * Returns %true if drain is performed and kernfs_mutex was temporarily 19145a140e5STejun Heo * released. %false if @kn was already drained and no operation was 19245a140e5STejun Heo * necessary. 19345a140e5STejun Heo * 19445a140e5STejun Heo * The caller is responsible for ensuring @kn stays pinned while this 19545a140e5STejun Heo * function is in progress even if it gets removed by someone else. 196fd7b9f7bSTejun Heo */ 19745a140e5STejun Heo static bool kernfs_drain(struct kernfs_node *kn) 19845a140e5STejun Heo __releases(&kernfs_mutex) __acquires(&kernfs_mutex) 199fd7b9f7bSTejun Heo { 200ea1c472dSTejun Heo struct kernfs_root *root = kernfs_root(kn); 201fd7b9f7bSTejun Heo 20245a140e5STejun Heo lockdep_assert_held(&kernfs_mutex); 203ae34372eSTejun Heo WARN_ON_ONCE(atomic_read(&kn->active) >= 0); 204ea1c472dSTejun Heo 20545a140e5STejun Heo /* 20645a140e5STejun Heo * We want to go through the active ref lockdep annotation at least 20745a140e5STejun Heo * once for all node removals, but the lockdep annotation can't be 20845a140e5STejun Heo * nested inside kernfs_mutex and deactivation can't make forward 20945a140e5STejun Heo * progress if we keep dropping the mutex. Use JUST_ACTIVATED to 21045a140e5STejun Heo * force the slow path once for each deactivation if lockdep is 21145a140e5STejun Heo * enabled. 21245a140e5STejun Heo */ 21345a140e5STejun Heo if ((!kernfs_lockdep(kn) || !(kn->flags & KERNFS_JUST_DEACTIVATED)) && 21445a140e5STejun Heo atomic_read(&kn->active) == KN_DEACTIVATED_BIAS) 21545a140e5STejun Heo return false; 21645a140e5STejun Heo 21745a140e5STejun Heo kn->flags &= ~KERNFS_JUST_DEACTIVATED; 21845a140e5STejun Heo mutex_unlock(&kernfs_mutex); 21945a140e5STejun Heo 220a69d001cSTejun Heo if (kernfs_lockdep(kn)) { 221a69d001cSTejun Heo rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_); 222ea1c472dSTejun Heo if (atomic_read(&kn->active) != KN_DEACTIVATED_BIAS) 223324a56e1STejun Heo lock_contended(&kn->dep_map, _RET_IP_); 224a69d001cSTejun Heo } 225ea1c472dSTejun Heo 226ea1c472dSTejun Heo wait_event(root->deactivate_waitq, 227ea1c472dSTejun Heo atomic_read(&kn->active) == KN_DEACTIVATED_BIAS); 228fd7b9f7bSTejun Heo 229a69d001cSTejun Heo if (kernfs_lockdep(kn)) { 230324a56e1STejun Heo lock_acquired(&kn->dep_map, _RET_IP_); 231324a56e1STejun Heo rwsem_release(&kn->dep_map, 1, _RET_IP_); 232fd7b9f7bSTejun Heo } 23345a140e5STejun Heo 23445a140e5STejun Heo mutex_lock(&kernfs_mutex); 23545a140e5STejun Heo return true; 236a69d001cSTejun Heo } 237fd7b9f7bSTejun Heo 238fd7b9f7bSTejun Heo /** 239324a56e1STejun Heo * kernfs_get - get a reference count on a kernfs_node 240324a56e1STejun Heo * @kn: the target kernfs_node 241fd7b9f7bSTejun Heo */ 242324a56e1STejun Heo void kernfs_get(struct kernfs_node *kn) 243fd7b9f7bSTejun Heo { 244324a56e1STejun Heo if (kn) { 245adc5e8b5STejun Heo WARN_ON(!atomic_read(&kn->count)); 246adc5e8b5STejun Heo atomic_inc(&kn->count); 247fd7b9f7bSTejun Heo } 248fd7b9f7bSTejun Heo } 249fd7b9f7bSTejun Heo EXPORT_SYMBOL_GPL(kernfs_get); 250fd7b9f7bSTejun Heo 251fd7b9f7bSTejun Heo /** 252324a56e1STejun Heo * kernfs_put - put a reference count on a kernfs_node 253324a56e1STejun Heo * @kn: the target kernfs_node 254fd7b9f7bSTejun Heo * 255324a56e1STejun Heo * Put a reference count of @kn and destroy it if it reached zero. 256fd7b9f7bSTejun Heo */ 257324a56e1STejun Heo void kernfs_put(struct kernfs_node *kn) 258fd7b9f7bSTejun Heo { 259324a56e1STejun Heo struct kernfs_node *parent; 260ba7443bcSTejun Heo struct kernfs_root *root; 261fd7b9f7bSTejun Heo 262adc5e8b5STejun Heo if (!kn || !atomic_dec_and_test(&kn->count)) 263fd7b9f7bSTejun Heo return; 264324a56e1STejun Heo root = kernfs_root(kn); 265fd7b9f7bSTejun Heo repeat: 266ae34372eSTejun Heo /* 267ae34372eSTejun Heo * Moving/renaming is always done while holding reference. 268adc5e8b5STejun Heo * kn->parent won't change beneath us. 269fd7b9f7bSTejun Heo */ 270adc5e8b5STejun Heo parent = kn->parent; 271fd7b9f7bSTejun Heo 272ae34372eSTejun Heo WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS, 273ae34372eSTejun Heo "kernfs_put: %s/%s: released with incorrect active_ref %d\n", 274ae34372eSTejun Heo parent ? parent->name : "", kn->name, atomic_read(&kn->active)); 275fd7b9f7bSTejun Heo 276df23fc39STejun Heo if (kernfs_type(kn) == KERNFS_LINK) 277adc5e8b5STejun Heo kernfs_put(kn->symlink.target_kn); 2782063d608STejun Heo if (!(kn->flags & KERNFS_STATIC_NAME)) 279adc5e8b5STejun Heo kfree(kn->name); 280adc5e8b5STejun Heo if (kn->iattr) { 281adc5e8b5STejun Heo if (kn->iattr->ia_secdata) 282adc5e8b5STejun Heo security_release_secctx(kn->iattr->ia_secdata, 283adc5e8b5STejun Heo kn->iattr->ia_secdata_len); 284adc5e8b5STejun Heo simple_xattrs_free(&kn->iattr->xattrs); 2852322392bSTejun Heo } 286adc5e8b5STejun Heo kfree(kn->iattr); 287adc5e8b5STejun Heo ida_simple_remove(&root->ino_ida, kn->ino); 288a797bfc3STejun Heo kmem_cache_free(kernfs_node_cache, kn); 289fd7b9f7bSTejun Heo 290324a56e1STejun Heo kn = parent; 291324a56e1STejun Heo if (kn) { 292adc5e8b5STejun Heo if (atomic_dec_and_test(&kn->count)) 293fd7b9f7bSTejun Heo goto repeat; 294ba7443bcSTejun Heo } else { 295324a56e1STejun Heo /* just released the root kn, free @root too */ 296bc755553STejun Heo ida_destroy(&root->ino_ida); 297ba7443bcSTejun Heo kfree(root); 298ba7443bcSTejun Heo } 299fd7b9f7bSTejun Heo } 300fd7b9f7bSTejun Heo EXPORT_SYMBOL_GPL(kernfs_put); 301fd7b9f7bSTejun Heo 302c637b8acSTejun Heo static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags) 303fd7b9f7bSTejun Heo { 304324a56e1STejun Heo struct kernfs_node *kn; 305fd7b9f7bSTejun Heo 306fd7b9f7bSTejun Heo if (flags & LOOKUP_RCU) 307fd7b9f7bSTejun Heo return -ECHILD; 308fd7b9f7bSTejun Heo 30919bbb926STejun Heo /* Always perform fresh lookup for negatives */ 31019bbb926STejun Heo if (!dentry->d_inode) 31119bbb926STejun Heo goto out_bad_unlocked; 31219bbb926STejun Heo 313324a56e1STejun Heo kn = dentry->d_fsdata; 314a797bfc3STejun Heo mutex_lock(&kernfs_mutex); 315fd7b9f7bSTejun Heo 316ae34372eSTejun Heo /* Force fresh lookup if removed */ 317ae34372eSTejun Heo if (kn->parent && RB_EMPTY_NODE(&kn->rb)) 318fd7b9f7bSTejun Heo goto out_bad; 319fd7b9f7bSTejun Heo 320c637b8acSTejun Heo /* The kernfs node has been moved? */ 321adc5e8b5STejun Heo if (dentry->d_parent->d_fsdata != kn->parent) 322fd7b9f7bSTejun Heo goto out_bad; 323fd7b9f7bSTejun Heo 324c637b8acSTejun Heo /* The kernfs node has been renamed */ 325adc5e8b5STejun Heo if (strcmp(dentry->d_name.name, kn->name) != 0) 326fd7b9f7bSTejun Heo goto out_bad; 327fd7b9f7bSTejun Heo 328c637b8acSTejun Heo /* The kernfs node has been moved to a different namespace */ 329adc5e8b5STejun Heo if (kn->parent && kernfs_ns_enabled(kn->parent) && 330c525aaddSTejun Heo kernfs_info(dentry->d_sb)->ns != kn->ns) 331fd7b9f7bSTejun Heo goto out_bad; 332fd7b9f7bSTejun Heo 333a797bfc3STejun Heo mutex_unlock(&kernfs_mutex); 334fd7b9f7bSTejun Heo out_valid: 335fd7b9f7bSTejun Heo return 1; 336fd7b9f7bSTejun Heo out_bad: 337a797bfc3STejun Heo mutex_unlock(&kernfs_mutex); 33819bbb926STejun Heo out_bad_unlocked: 33919bbb926STejun Heo /* 34019bbb926STejun Heo * @dentry doesn't match the underlying kernfs node, drop the 34119bbb926STejun Heo * dentry and force lookup. If we have submounts we must allow the 34219bbb926STejun Heo * vfs caches to lie about the state of the filesystem to prevent 34319bbb926STejun Heo * leaks and other nasty things, so use check_submounts_and_drop() 34419bbb926STejun Heo * instead of d_drop(). 345fd7b9f7bSTejun Heo */ 346fd7b9f7bSTejun Heo if (check_submounts_and_drop(dentry) != 0) 347fd7b9f7bSTejun Heo goto out_valid; 348fd7b9f7bSTejun Heo 349fd7b9f7bSTejun Heo return 0; 350fd7b9f7bSTejun Heo } 351fd7b9f7bSTejun Heo 352c637b8acSTejun Heo static void kernfs_dop_release(struct dentry *dentry) 353fd7b9f7bSTejun Heo { 354fd7b9f7bSTejun Heo kernfs_put(dentry->d_fsdata); 355fd7b9f7bSTejun Heo } 356fd7b9f7bSTejun Heo 357a797bfc3STejun Heo const struct dentry_operations kernfs_dops = { 358c637b8acSTejun Heo .d_revalidate = kernfs_dop_revalidate, 359c637b8acSTejun Heo .d_release = kernfs_dop_release, 360fd7b9f7bSTejun Heo }; 361fd7b9f7bSTejun Heo 362c637b8acSTejun Heo struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, 3632063d608STejun Heo umode_t mode, unsigned flags) 364fd7b9f7bSTejun Heo { 365fd7b9f7bSTejun Heo char *dup_name = NULL; 366324a56e1STejun Heo struct kernfs_node *kn; 367bc755553STejun Heo int ret; 368fd7b9f7bSTejun Heo 3692063d608STejun Heo if (!(flags & KERNFS_STATIC_NAME)) { 370fd7b9f7bSTejun Heo name = dup_name = kstrdup(name, GFP_KERNEL); 371fd7b9f7bSTejun Heo if (!name) 372fd7b9f7bSTejun Heo return NULL; 373fd7b9f7bSTejun Heo } 374fd7b9f7bSTejun Heo 375a797bfc3STejun Heo kn = kmem_cache_zalloc(kernfs_node_cache, GFP_KERNEL); 376324a56e1STejun Heo if (!kn) 377fd7b9f7bSTejun Heo goto err_out1; 378fd7b9f7bSTejun Heo 379bc755553STejun Heo ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL); 380bc755553STejun Heo if (ret < 0) 381fd7b9f7bSTejun Heo goto err_out2; 382adc5e8b5STejun Heo kn->ino = ret; 383fd7b9f7bSTejun Heo 384adc5e8b5STejun Heo atomic_set(&kn->count, 1); 385ae34372eSTejun Heo atomic_set(&kn->active, KN_DEACTIVATED_BIAS); 386ae34372eSTejun Heo RB_CLEAR_NODE(&kn->rb); 387fd7b9f7bSTejun Heo 388adc5e8b5STejun Heo kn->name = name; 389adc5e8b5STejun Heo kn->mode = mode; 390ae34372eSTejun Heo kn->flags = flags; 391fd7b9f7bSTejun Heo 392324a56e1STejun Heo return kn; 393fd7b9f7bSTejun Heo 394fd7b9f7bSTejun Heo err_out2: 395a797bfc3STejun Heo kmem_cache_free(kernfs_node_cache, kn); 396fd7b9f7bSTejun Heo err_out1: 397fd7b9f7bSTejun Heo kfree(dup_name); 398fd7b9f7bSTejun Heo return NULL; 399fd7b9f7bSTejun Heo } 400fd7b9f7bSTejun Heo 401fd7b9f7bSTejun Heo /** 402c637b8acSTejun Heo * kernfs_add_one - add kernfs_node to parent without warning 403324a56e1STejun Heo * @kn: kernfs_node to be added 404324a56e1STejun Heo * @parent: the parent kernfs_node to add @kn to 405fd7b9f7bSTejun Heo * 406adc5e8b5STejun Heo * Get @parent and set @kn->parent to it and increment nlink of the 407adc5e8b5STejun Heo * parent inode if @kn is a directory and link into the children list 408adc5e8b5STejun Heo * of the parent. 409fd7b9f7bSTejun Heo * 410fd7b9f7bSTejun Heo * RETURNS: 411fd7b9f7bSTejun Heo * 0 on success, -EEXIST if entry with the given name already 412fd7b9f7bSTejun Heo * exists. 413fd7b9f7bSTejun Heo */ 41499177a34STejun Heo int kernfs_add_one(struct kernfs_node *kn, struct kernfs_node *parent) 415fd7b9f7bSTejun Heo { 416c525aaddSTejun Heo struct kernfs_iattrs *ps_iattr; 41799177a34STejun Heo bool has_ns; 418fd7b9f7bSTejun Heo int ret; 419fd7b9f7bSTejun Heo 42099177a34STejun Heo if (!kernfs_get_active(parent)) 42199177a34STejun Heo return -ENOENT; 422ae34372eSTejun Heo 42399177a34STejun Heo mutex_lock(&kernfs_mutex); 42499177a34STejun Heo 42599177a34STejun Heo ret = -EINVAL; 42699177a34STejun Heo has_ns = kernfs_ns_enabled(parent); 42799177a34STejun Heo if (WARN(has_ns != (bool)kn->ns, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", 42899177a34STejun Heo has_ns ? "required" : "invalid", parent->name, kn->name)) 42999177a34STejun Heo goto out_unlock; 430fd7b9f7bSTejun Heo 431df23fc39STejun Heo if (kernfs_type(parent) != KERNFS_DIR) 43299177a34STejun Heo goto out_unlock; 433fd7b9f7bSTejun Heo 434c637b8acSTejun Heo kn->hash = kernfs_name_hash(kn->name, kn->ns); 435adc5e8b5STejun Heo kn->parent = parent; 436324a56e1STejun Heo kernfs_get(parent); 437fd7b9f7bSTejun Heo 438c637b8acSTejun Heo ret = kernfs_link_sibling(kn); 439fd7b9f7bSTejun Heo if (ret) 44099177a34STejun Heo goto out_unlock; 441fd7b9f7bSTejun Heo 442fd7b9f7bSTejun Heo /* Update timestamps on the parent */ 443adc5e8b5STejun Heo ps_iattr = parent->iattr; 444fd7b9f7bSTejun Heo if (ps_iattr) { 445fd7b9f7bSTejun Heo struct iattr *ps_iattrs = &ps_iattr->ia_iattr; 446fd7b9f7bSTejun Heo ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; 447fd7b9f7bSTejun Heo } 448fd7b9f7bSTejun Heo 449fd7b9f7bSTejun Heo /* Mark the entry added into directory tree */ 450ae34372eSTejun Heo atomic_sub(KN_DEACTIVATED_BIAS, &kn->active); 45199177a34STejun Heo ret = 0; 45299177a34STejun Heo out_unlock: 453a797bfc3STejun Heo mutex_unlock(&kernfs_mutex); 45499177a34STejun Heo kernfs_put_active(parent); 45599177a34STejun Heo return ret; 456fd7b9f7bSTejun Heo } 457fd7b9f7bSTejun Heo 458fd7b9f7bSTejun Heo /** 459324a56e1STejun Heo * kernfs_find_ns - find kernfs_node with the given name 460324a56e1STejun Heo * @parent: kernfs_node to search under 461fd7b9f7bSTejun Heo * @name: name to look for 462fd7b9f7bSTejun Heo * @ns: the namespace tag to use 463fd7b9f7bSTejun Heo * 464324a56e1STejun Heo * Look for kernfs_node with name @name under @parent. Returns pointer to 465324a56e1STejun Heo * the found kernfs_node on success, %NULL on failure. 466fd7b9f7bSTejun Heo */ 467324a56e1STejun Heo static struct kernfs_node *kernfs_find_ns(struct kernfs_node *parent, 468fd7b9f7bSTejun Heo const unsigned char *name, 469fd7b9f7bSTejun Heo const void *ns) 470fd7b9f7bSTejun Heo { 471adc5e8b5STejun Heo struct rb_node *node = parent->dir.children.rb_node; 472ac9bba03STejun Heo bool has_ns = kernfs_ns_enabled(parent); 473fd7b9f7bSTejun Heo unsigned int hash; 474fd7b9f7bSTejun Heo 475a797bfc3STejun Heo lockdep_assert_held(&kernfs_mutex); 476fd7b9f7bSTejun Heo 477fd7b9f7bSTejun Heo if (has_ns != (bool)ns) { 478c637b8acSTejun Heo WARN(1, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", 479adc5e8b5STejun Heo has_ns ? "required" : "invalid", parent->name, name); 480fd7b9f7bSTejun Heo return NULL; 481fd7b9f7bSTejun Heo } 482fd7b9f7bSTejun Heo 483c637b8acSTejun Heo hash = kernfs_name_hash(name, ns); 484fd7b9f7bSTejun Heo while (node) { 485324a56e1STejun Heo struct kernfs_node *kn; 486fd7b9f7bSTejun Heo int result; 487fd7b9f7bSTejun Heo 488324a56e1STejun Heo kn = rb_to_kn(node); 489c637b8acSTejun Heo result = kernfs_name_compare(hash, name, ns, kn); 490fd7b9f7bSTejun Heo if (result < 0) 491fd7b9f7bSTejun Heo node = node->rb_left; 492fd7b9f7bSTejun Heo else if (result > 0) 493fd7b9f7bSTejun Heo node = node->rb_right; 494fd7b9f7bSTejun Heo else 495324a56e1STejun Heo return kn; 496fd7b9f7bSTejun Heo } 497fd7b9f7bSTejun Heo return NULL; 498fd7b9f7bSTejun Heo } 499fd7b9f7bSTejun Heo 500fd7b9f7bSTejun Heo /** 501324a56e1STejun Heo * kernfs_find_and_get_ns - find and get kernfs_node with the given name 502324a56e1STejun Heo * @parent: kernfs_node to search under 503fd7b9f7bSTejun Heo * @name: name to look for 504fd7b9f7bSTejun Heo * @ns: the namespace tag to use 505fd7b9f7bSTejun Heo * 506324a56e1STejun Heo * Look for kernfs_node with name @name under @parent and get a reference 507fd7b9f7bSTejun Heo * if found. This function may sleep and returns pointer to the found 508324a56e1STejun Heo * kernfs_node on success, %NULL on failure. 509fd7b9f7bSTejun Heo */ 510324a56e1STejun Heo struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent, 511fd7b9f7bSTejun Heo const char *name, const void *ns) 512fd7b9f7bSTejun Heo { 513324a56e1STejun Heo struct kernfs_node *kn; 514fd7b9f7bSTejun Heo 515a797bfc3STejun Heo mutex_lock(&kernfs_mutex); 516324a56e1STejun Heo kn = kernfs_find_ns(parent, name, ns); 517324a56e1STejun Heo kernfs_get(kn); 518a797bfc3STejun Heo mutex_unlock(&kernfs_mutex); 519fd7b9f7bSTejun Heo 520324a56e1STejun Heo return kn; 521fd7b9f7bSTejun Heo } 522fd7b9f7bSTejun Heo EXPORT_SYMBOL_GPL(kernfs_find_and_get_ns); 523fd7b9f7bSTejun Heo 524fd7b9f7bSTejun Heo /** 525ba7443bcSTejun Heo * kernfs_create_root - create a new kernfs hierarchy 52680b9bbefSTejun Heo * @kdops: optional directory syscall operations for the hierarchy 527ba7443bcSTejun Heo * @priv: opaque data associated with the new directory 528ba7443bcSTejun Heo * 529ba7443bcSTejun Heo * Returns the root of the new hierarchy on success, ERR_PTR() value on 530ba7443bcSTejun Heo * failure. 531ba7443bcSTejun Heo */ 53280b9bbefSTejun Heo struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv) 533ba7443bcSTejun Heo { 534ba7443bcSTejun Heo struct kernfs_root *root; 535324a56e1STejun Heo struct kernfs_node *kn; 536ba7443bcSTejun Heo 537ba7443bcSTejun Heo root = kzalloc(sizeof(*root), GFP_KERNEL); 538ba7443bcSTejun Heo if (!root) 539ba7443bcSTejun Heo return ERR_PTR(-ENOMEM); 540ba7443bcSTejun Heo 541bc755553STejun Heo ida_init(&root->ino_ida); 542bc755553STejun Heo 543c637b8acSTejun Heo kn = kernfs_new_node(root, "", S_IFDIR | S_IRUGO | S_IXUGO, KERNFS_DIR); 544324a56e1STejun Heo if (!kn) { 545bc755553STejun Heo ida_destroy(&root->ino_ida); 546ba7443bcSTejun Heo kfree(root); 547ba7443bcSTejun Heo return ERR_PTR(-ENOMEM); 548ba7443bcSTejun Heo } 549ba7443bcSTejun Heo 550ae34372eSTejun Heo atomic_sub(KN_DEACTIVATED_BIAS, &kn->active); 551324a56e1STejun Heo kn->priv = priv; 552adc5e8b5STejun Heo kn->dir.root = root; 553ba7443bcSTejun Heo 55480b9bbefSTejun Heo root->dir_ops = kdops; 555324a56e1STejun Heo root->kn = kn; 556ea1c472dSTejun Heo init_waitqueue_head(&root->deactivate_waitq); 557ba7443bcSTejun Heo 558ba7443bcSTejun Heo return root; 559ba7443bcSTejun Heo } 560ba7443bcSTejun Heo 561ba7443bcSTejun Heo /** 562ba7443bcSTejun Heo * kernfs_destroy_root - destroy a kernfs hierarchy 563ba7443bcSTejun Heo * @root: root of the hierarchy to destroy 564ba7443bcSTejun Heo * 565ba7443bcSTejun Heo * Destroy the hierarchy anchored at @root by removing all existing 566ba7443bcSTejun Heo * directories and destroying @root. 567ba7443bcSTejun Heo */ 568ba7443bcSTejun Heo void kernfs_destroy_root(struct kernfs_root *root) 569ba7443bcSTejun Heo { 570324a56e1STejun Heo kernfs_remove(root->kn); /* will also free @root */ 571ba7443bcSTejun Heo } 572ba7443bcSTejun Heo 573ba7443bcSTejun Heo /** 574fd7b9f7bSTejun Heo * kernfs_create_dir_ns - create a directory 575fd7b9f7bSTejun Heo * @parent: parent in which to create a new directory 576fd7b9f7bSTejun Heo * @name: name of the new directory 577bb8b9d09STejun Heo * @mode: mode of the new directory 578fd7b9f7bSTejun Heo * @priv: opaque data associated with the new directory 579fd7b9f7bSTejun Heo * @ns: optional namespace tag of the directory 580fd7b9f7bSTejun Heo * 581fd7b9f7bSTejun Heo * Returns the created node on success, ERR_PTR() value on failure. 582fd7b9f7bSTejun Heo */ 583324a56e1STejun Heo struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, 584bb8b9d09STejun Heo const char *name, umode_t mode, 585bb8b9d09STejun Heo void *priv, const void *ns) 586fd7b9f7bSTejun Heo { 587324a56e1STejun Heo struct kernfs_node *kn; 588fd7b9f7bSTejun Heo int rc; 589fd7b9f7bSTejun Heo 590fd7b9f7bSTejun Heo /* allocate */ 591bb8b9d09STejun Heo kn = kernfs_new_node(kernfs_root(parent), name, mode | S_IFDIR, 592bb8b9d09STejun Heo KERNFS_DIR); 593324a56e1STejun Heo if (!kn) 594fd7b9f7bSTejun Heo return ERR_PTR(-ENOMEM); 595fd7b9f7bSTejun Heo 596adc5e8b5STejun Heo kn->dir.root = parent->dir.root; 597adc5e8b5STejun Heo kn->ns = ns; 598324a56e1STejun Heo kn->priv = priv; 599fd7b9f7bSTejun Heo 600fd7b9f7bSTejun Heo /* link in */ 60199177a34STejun Heo rc = kernfs_add_one(kn, parent); 602fd7b9f7bSTejun Heo if (!rc) 603324a56e1STejun Heo return kn; 604fd7b9f7bSTejun Heo 605324a56e1STejun Heo kernfs_put(kn); 606fd7b9f7bSTejun Heo return ERR_PTR(rc); 607fd7b9f7bSTejun Heo } 608fd7b9f7bSTejun Heo 609c637b8acSTejun Heo static struct dentry *kernfs_iop_lookup(struct inode *dir, 610c637b8acSTejun Heo struct dentry *dentry, 611fd7b9f7bSTejun Heo unsigned int flags) 612fd7b9f7bSTejun Heo { 61319bbb926STejun Heo struct dentry *ret; 614324a56e1STejun Heo struct kernfs_node *parent = dentry->d_parent->d_fsdata; 615324a56e1STejun Heo struct kernfs_node *kn; 616fd7b9f7bSTejun Heo struct inode *inode; 617fd7b9f7bSTejun Heo const void *ns = NULL; 618fd7b9f7bSTejun Heo 619a797bfc3STejun Heo mutex_lock(&kernfs_mutex); 620fd7b9f7bSTejun Heo 621324a56e1STejun Heo if (kernfs_ns_enabled(parent)) 622c525aaddSTejun Heo ns = kernfs_info(dir->i_sb)->ns; 623fd7b9f7bSTejun Heo 624324a56e1STejun Heo kn = kernfs_find_ns(parent, dentry->d_name.name, ns); 625fd7b9f7bSTejun Heo 626fd7b9f7bSTejun Heo /* no such entry */ 627324a56e1STejun Heo if (!kn) { 62819bbb926STejun Heo ret = NULL; 629fd7b9f7bSTejun Heo goto out_unlock; 630fd7b9f7bSTejun Heo } 631324a56e1STejun Heo kernfs_get(kn); 632324a56e1STejun Heo dentry->d_fsdata = kn; 633fd7b9f7bSTejun Heo 634fd7b9f7bSTejun Heo /* attach dentry and inode */ 635c637b8acSTejun Heo inode = kernfs_get_inode(dir->i_sb, kn); 636fd7b9f7bSTejun Heo if (!inode) { 637fd7b9f7bSTejun Heo ret = ERR_PTR(-ENOMEM); 638fd7b9f7bSTejun Heo goto out_unlock; 639fd7b9f7bSTejun Heo } 640fd7b9f7bSTejun Heo 641fd7b9f7bSTejun Heo /* instantiate and hash dentry */ 642fd7b9f7bSTejun Heo ret = d_materialise_unique(dentry, inode); 643fd7b9f7bSTejun Heo out_unlock: 644a797bfc3STejun Heo mutex_unlock(&kernfs_mutex); 645fd7b9f7bSTejun Heo return ret; 646fd7b9f7bSTejun Heo } 647fd7b9f7bSTejun Heo 64880b9bbefSTejun Heo static int kernfs_iop_mkdir(struct inode *dir, struct dentry *dentry, 64980b9bbefSTejun Heo umode_t mode) 65080b9bbefSTejun Heo { 65180b9bbefSTejun Heo struct kernfs_node *parent = dir->i_private; 65280b9bbefSTejun Heo struct kernfs_dir_ops *kdops = kernfs_root(parent)->dir_ops; 65380b9bbefSTejun Heo 65480b9bbefSTejun Heo if (!kdops || !kdops->mkdir) 65580b9bbefSTejun Heo return -EPERM; 65680b9bbefSTejun Heo 65780b9bbefSTejun Heo return kdops->mkdir(parent, dentry->d_name.name, mode); 65880b9bbefSTejun Heo } 65980b9bbefSTejun Heo 66080b9bbefSTejun Heo static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry) 66180b9bbefSTejun Heo { 66280b9bbefSTejun Heo struct kernfs_node *kn = dentry->d_fsdata; 66380b9bbefSTejun Heo struct kernfs_dir_ops *kdops = kernfs_root(kn)->dir_ops; 66480b9bbefSTejun Heo 66580b9bbefSTejun Heo if (!kdops || !kdops->rmdir) 66680b9bbefSTejun Heo return -EPERM; 66780b9bbefSTejun Heo 66880b9bbefSTejun Heo return kdops->rmdir(kn); 66980b9bbefSTejun Heo } 67080b9bbefSTejun Heo 67180b9bbefSTejun Heo static int kernfs_iop_rename(struct inode *old_dir, struct dentry *old_dentry, 67280b9bbefSTejun Heo struct inode *new_dir, struct dentry *new_dentry) 67380b9bbefSTejun Heo { 67480b9bbefSTejun Heo struct kernfs_node *kn = old_dentry->d_fsdata; 67580b9bbefSTejun Heo struct kernfs_node *new_parent = new_dir->i_private; 67680b9bbefSTejun Heo struct kernfs_dir_ops *kdops = kernfs_root(kn)->dir_ops; 67780b9bbefSTejun Heo 67880b9bbefSTejun Heo if (!kdops || !kdops->rename) 67980b9bbefSTejun Heo return -EPERM; 68080b9bbefSTejun Heo 68180b9bbefSTejun Heo return kdops->rename(kn, new_parent, new_dentry->d_name.name); 68280b9bbefSTejun Heo } 68380b9bbefSTejun Heo 684a797bfc3STejun Heo const struct inode_operations kernfs_dir_iops = { 685c637b8acSTejun Heo .lookup = kernfs_iop_lookup, 686c637b8acSTejun Heo .permission = kernfs_iop_permission, 687c637b8acSTejun Heo .setattr = kernfs_iop_setattr, 688c637b8acSTejun Heo .getattr = kernfs_iop_getattr, 689c637b8acSTejun Heo .setxattr = kernfs_iop_setxattr, 690c637b8acSTejun Heo .removexattr = kernfs_iop_removexattr, 691c637b8acSTejun Heo .getxattr = kernfs_iop_getxattr, 692c637b8acSTejun Heo .listxattr = kernfs_iop_listxattr, 69380b9bbefSTejun Heo 69480b9bbefSTejun Heo .mkdir = kernfs_iop_mkdir, 69580b9bbefSTejun Heo .rmdir = kernfs_iop_rmdir, 69680b9bbefSTejun Heo .rename = kernfs_iop_rename, 697fd7b9f7bSTejun Heo }; 698fd7b9f7bSTejun Heo 699c637b8acSTejun Heo static struct kernfs_node *kernfs_leftmost_descendant(struct kernfs_node *pos) 700fd7b9f7bSTejun Heo { 701324a56e1STejun Heo struct kernfs_node *last; 702fd7b9f7bSTejun Heo 703fd7b9f7bSTejun Heo while (true) { 704fd7b9f7bSTejun Heo struct rb_node *rbn; 705fd7b9f7bSTejun Heo 706fd7b9f7bSTejun Heo last = pos; 707fd7b9f7bSTejun Heo 708df23fc39STejun Heo if (kernfs_type(pos) != KERNFS_DIR) 709fd7b9f7bSTejun Heo break; 710fd7b9f7bSTejun Heo 711adc5e8b5STejun Heo rbn = rb_first(&pos->dir.children); 712fd7b9f7bSTejun Heo if (!rbn) 713fd7b9f7bSTejun Heo break; 714fd7b9f7bSTejun Heo 715324a56e1STejun Heo pos = rb_to_kn(rbn); 716fd7b9f7bSTejun Heo } 717fd7b9f7bSTejun Heo 718fd7b9f7bSTejun Heo return last; 719fd7b9f7bSTejun Heo } 720fd7b9f7bSTejun Heo 721fd7b9f7bSTejun Heo /** 722c637b8acSTejun Heo * kernfs_next_descendant_post - find the next descendant for post-order walk 723fd7b9f7bSTejun Heo * @pos: the current position (%NULL to initiate traversal) 724324a56e1STejun Heo * @root: kernfs_node whose descendants to walk 725fd7b9f7bSTejun Heo * 726fd7b9f7bSTejun Heo * Find the next descendant to visit for post-order traversal of @root's 727fd7b9f7bSTejun Heo * descendants. @root is included in the iteration and the last node to be 728fd7b9f7bSTejun Heo * visited. 729fd7b9f7bSTejun Heo */ 730c637b8acSTejun Heo static struct kernfs_node *kernfs_next_descendant_post(struct kernfs_node *pos, 731324a56e1STejun Heo struct kernfs_node *root) 732fd7b9f7bSTejun Heo { 733fd7b9f7bSTejun Heo struct rb_node *rbn; 734fd7b9f7bSTejun Heo 735a797bfc3STejun Heo lockdep_assert_held(&kernfs_mutex); 736fd7b9f7bSTejun Heo 737fd7b9f7bSTejun Heo /* if first iteration, visit leftmost descendant which may be root */ 738fd7b9f7bSTejun Heo if (!pos) 739c637b8acSTejun Heo return kernfs_leftmost_descendant(root); 740fd7b9f7bSTejun Heo 741fd7b9f7bSTejun Heo /* if we visited @root, we're done */ 742fd7b9f7bSTejun Heo if (pos == root) 743fd7b9f7bSTejun Heo return NULL; 744fd7b9f7bSTejun Heo 745fd7b9f7bSTejun Heo /* if there's an unvisited sibling, visit its leftmost descendant */ 746adc5e8b5STejun Heo rbn = rb_next(&pos->rb); 747fd7b9f7bSTejun Heo if (rbn) 748c637b8acSTejun Heo return kernfs_leftmost_descendant(rb_to_kn(rbn)); 749fd7b9f7bSTejun Heo 750fd7b9f7bSTejun Heo /* no sibling left, visit parent */ 751adc5e8b5STejun Heo return pos->parent; 752fd7b9f7bSTejun Heo } 753fd7b9f7bSTejun Heo 75445a140e5STejun Heo static void __kernfs_deactivate(struct kernfs_node *kn) 75545a140e5STejun Heo { 75645a140e5STejun Heo struct kernfs_node *pos; 75745a140e5STejun Heo 75845a140e5STejun Heo lockdep_assert_held(&kernfs_mutex); 75945a140e5STejun Heo 76045a140e5STejun Heo /* prevent any new usage under @kn by deactivating all nodes */ 76145a140e5STejun Heo pos = NULL; 76245a140e5STejun Heo while ((pos = kernfs_next_descendant_post(pos, kn))) { 7639b0925a6SGreg Kroah-Hartman if (atomic_read(&pos->active) >= 0) { 76445a140e5STejun Heo atomic_add(KN_DEACTIVATED_BIAS, &pos->active); 76545a140e5STejun Heo pos->flags |= KERNFS_JUST_DEACTIVATED; 76645a140e5STejun Heo } 76745a140e5STejun Heo } 76845a140e5STejun Heo 76945a140e5STejun Heo /* 77045a140e5STejun Heo * Drain the subtree. If kernfs_drain() blocked to drain, which is 77145a140e5STejun Heo * indicated by %true return, it temporarily released kernfs_mutex 77245a140e5STejun Heo * and the rbtree might have been modified inbetween breaking our 77345a140e5STejun Heo * future walk. Restart the walk after each %true return. 77445a140e5STejun Heo */ 77545a140e5STejun Heo pos = NULL; 77645a140e5STejun Heo while ((pos = kernfs_next_descendant_post(pos, kn))) { 77745a140e5STejun Heo bool drained; 77845a140e5STejun Heo 77945a140e5STejun Heo kernfs_get(pos); 78045a140e5STejun Heo drained = kernfs_drain(pos); 78145a140e5STejun Heo kernfs_put(pos); 78245a140e5STejun Heo if (drained) 78345a140e5STejun Heo pos = NULL; 78445a140e5STejun Heo } 78545a140e5STejun Heo } 78645a140e5STejun Heo 78799177a34STejun Heo static void __kernfs_remove(struct kernfs_node *kn) 788fd7b9f7bSTejun Heo { 78945a140e5STejun Heo struct kernfs_node *pos; 79045a140e5STejun Heo 79145a140e5STejun Heo lockdep_assert_held(&kernfs_mutex); 792fd7b9f7bSTejun Heo 793ce9b499cSGreg Kroah-Hartman if (!kn) 794ce9b499cSGreg Kroah-Hartman return; 795ce9b499cSGreg Kroah-Hartman 796c637b8acSTejun Heo pr_debug("kernfs %s: removing\n", kn->name); 797fd7b9f7bSTejun Heo 79845a140e5STejun Heo __kernfs_deactivate(kn); 79945a140e5STejun Heo 80045a140e5STejun Heo /* unlink the subtree node-by-node */ 801fd7b9f7bSTejun Heo do { 80245a140e5STejun Heo pos = kernfs_leftmost_descendant(kn); 80345a140e5STejun Heo 804f601f9a2STejun Heo /* 805f601f9a2STejun Heo * We're gonna release kernfs_mutex to unmap bin files, 806f601f9a2STejun Heo * Make sure @pos doesn't go away inbetween. 807f601f9a2STejun Heo */ 808f601f9a2STejun Heo kernfs_get(pos); 809f601f9a2STejun Heo 810f601f9a2STejun Heo /* 811f601f9a2STejun Heo * This must be come before unlinking; otherwise, when 812f601f9a2STejun Heo * there are multiple removers, some may finish before 813f601f9a2STejun Heo * unmapping is complete. 814f601f9a2STejun Heo */ 815f601f9a2STejun Heo if (pos->flags & KERNFS_HAS_MMAP) { 816f601f9a2STejun Heo mutex_unlock(&kernfs_mutex); 817f601f9a2STejun Heo kernfs_unmap_file(pos); 818f601f9a2STejun Heo mutex_lock(&kernfs_mutex); 819f601f9a2STejun Heo } 820f601f9a2STejun Heo 821f601f9a2STejun Heo /* 822f601f9a2STejun Heo * kernfs_unlink_sibling() succeeds once per node. Use it 823f601f9a2STejun Heo * to decide who's responsible for cleanups. 824f601f9a2STejun Heo */ 825f601f9a2STejun Heo if (!pos->parent || kernfs_unlink_sibling(pos)) { 826f601f9a2STejun Heo struct kernfs_iattrs *ps_iattr = 827f601f9a2STejun Heo pos->parent ? pos->parent->iattr : NULL; 82845a140e5STejun Heo 82945a140e5STejun Heo /* update timestamps on the parent */ 83045a140e5STejun Heo if (ps_iattr) { 83145a140e5STejun Heo ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME; 83245a140e5STejun Heo ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; 83345a140e5STejun Heo } 83445a140e5STejun Heo 83599177a34STejun Heo kernfs_put(pos); 836f601f9a2STejun Heo } 837f601f9a2STejun Heo 838f601f9a2STejun Heo kernfs_put(pos); 83945a140e5STejun Heo } while (pos != kn); 840fd7b9f7bSTejun Heo } 841fd7b9f7bSTejun Heo 842fd7b9f7bSTejun Heo /** 843324a56e1STejun Heo * kernfs_remove - remove a kernfs_node recursively 844324a56e1STejun Heo * @kn: the kernfs_node to remove 845fd7b9f7bSTejun Heo * 846324a56e1STejun Heo * Remove @kn along with all its subdirectories and files. 847fd7b9f7bSTejun Heo */ 848324a56e1STejun Heo void kernfs_remove(struct kernfs_node *kn) 849fd7b9f7bSTejun Heo { 85099177a34STejun Heo mutex_lock(&kernfs_mutex); 85199177a34STejun Heo __kernfs_remove(kn); 85299177a34STejun Heo mutex_unlock(&kernfs_mutex); 853fd7b9f7bSTejun Heo } 854fd7b9f7bSTejun Heo 855fd7b9f7bSTejun Heo /** 856324a56e1STejun Heo * kernfs_remove_by_name_ns - find a kernfs_node by name and remove it 857324a56e1STejun Heo * @parent: parent of the target 858324a56e1STejun Heo * @name: name of the kernfs_node to remove 859324a56e1STejun Heo * @ns: namespace tag of the kernfs_node to remove 860fd7b9f7bSTejun Heo * 861324a56e1STejun Heo * Look for the kernfs_node with @name and @ns under @parent and remove it. 862324a56e1STejun Heo * Returns 0 on success, -ENOENT if such entry doesn't exist. 863fd7b9f7bSTejun Heo */ 864324a56e1STejun Heo int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, 865fd7b9f7bSTejun Heo const void *ns) 866fd7b9f7bSTejun Heo { 867324a56e1STejun Heo struct kernfs_node *kn; 868fd7b9f7bSTejun Heo 869324a56e1STejun Heo if (!parent) { 870c637b8acSTejun Heo WARN(1, KERN_WARNING "kernfs: can not remove '%s', no directory\n", 871fd7b9f7bSTejun Heo name); 872fd7b9f7bSTejun Heo return -ENOENT; 873fd7b9f7bSTejun Heo } 874fd7b9f7bSTejun Heo 87599177a34STejun Heo mutex_lock(&kernfs_mutex); 876fd7b9f7bSTejun Heo 877324a56e1STejun Heo kn = kernfs_find_ns(parent, name, ns); 878324a56e1STejun Heo if (kn) 87999177a34STejun Heo __kernfs_remove(kn); 880fd7b9f7bSTejun Heo 88199177a34STejun Heo mutex_unlock(&kernfs_mutex); 882fd7b9f7bSTejun Heo 883324a56e1STejun Heo if (kn) 884fd7b9f7bSTejun Heo return 0; 885fd7b9f7bSTejun Heo else 886fd7b9f7bSTejun Heo return -ENOENT; 887fd7b9f7bSTejun Heo } 888fd7b9f7bSTejun Heo 889fd7b9f7bSTejun Heo /** 890fd7b9f7bSTejun Heo * kernfs_rename_ns - move and rename a kernfs_node 891324a56e1STejun Heo * @kn: target node 892fd7b9f7bSTejun Heo * @new_parent: new parent to put @sd under 893fd7b9f7bSTejun Heo * @new_name: new name 894fd7b9f7bSTejun Heo * @new_ns: new namespace tag 895fd7b9f7bSTejun Heo */ 896324a56e1STejun Heo int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, 897fd7b9f7bSTejun Heo const char *new_name, const void *new_ns) 898fd7b9f7bSTejun Heo { 899fd7b9f7bSTejun Heo int error; 900fd7b9f7bSTejun Heo 901d0ae3d43STejun Heo error = -ENOENT; 902ae34372eSTejun Heo if (!kernfs_get_active(new_parent)) 903d0ae3d43STejun Heo goto out; 904ae34372eSTejun Heo if (!kernfs_get_active(kn)) 905ae34372eSTejun Heo goto out_put_new_parent; 906ae34372eSTejun Heo 907ae34372eSTejun Heo mutex_lock(&kernfs_mutex); 908d0ae3d43STejun Heo 909fd7b9f7bSTejun Heo error = 0; 910adc5e8b5STejun Heo if ((kn->parent == new_parent) && (kn->ns == new_ns) && 911adc5e8b5STejun Heo (strcmp(kn->name, new_name) == 0)) 912ae34372eSTejun Heo goto out_unlock; /* nothing to rename */ 913fd7b9f7bSTejun Heo 914fd7b9f7bSTejun Heo error = -EEXIST; 915fd7b9f7bSTejun Heo if (kernfs_find_ns(new_parent, new_name, new_ns)) 916ae34372eSTejun Heo goto out_unlock; 917fd7b9f7bSTejun Heo 918324a56e1STejun Heo /* rename kernfs_node */ 919adc5e8b5STejun Heo if (strcmp(kn->name, new_name) != 0) { 920fd7b9f7bSTejun Heo error = -ENOMEM; 921fd7b9f7bSTejun Heo new_name = kstrdup(new_name, GFP_KERNEL); 922fd7b9f7bSTejun Heo if (!new_name) 923ae34372eSTejun Heo goto out_unlock; 924fd7b9f7bSTejun Heo 92547a52e91STejun Heo if (kn->flags & KERNFS_STATIC_NAME) 92647a52e91STejun Heo kn->flags &= ~KERNFS_STATIC_NAME; 92747a52e91STejun Heo else 928adc5e8b5STejun Heo kfree(kn->name); 92947a52e91STejun Heo 930adc5e8b5STejun Heo kn->name = new_name; 931fd7b9f7bSTejun Heo } 932fd7b9f7bSTejun Heo 933fd7b9f7bSTejun Heo /* 934fd7b9f7bSTejun Heo * Move to the appropriate place in the appropriate directories rbtree. 935fd7b9f7bSTejun Heo */ 936c637b8acSTejun Heo kernfs_unlink_sibling(kn); 937fd7b9f7bSTejun Heo kernfs_get(new_parent); 938adc5e8b5STejun Heo kernfs_put(kn->parent); 939adc5e8b5STejun Heo kn->ns = new_ns; 940c637b8acSTejun Heo kn->hash = kernfs_name_hash(kn->name, kn->ns); 941adc5e8b5STejun Heo kn->parent = new_parent; 942c637b8acSTejun Heo kernfs_link_sibling(kn); 943fd7b9f7bSTejun Heo 944fd7b9f7bSTejun Heo error = 0; 945ae34372eSTejun Heo out_unlock: 946a797bfc3STejun Heo mutex_unlock(&kernfs_mutex); 947ae34372eSTejun Heo kernfs_put_active(kn); 948ae34372eSTejun Heo out_put_new_parent: 949ae34372eSTejun Heo kernfs_put_active(new_parent); 950ae34372eSTejun Heo out: 951fd7b9f7bSTejun Heo return error; 952fd7b9f7bSTejun Heo } 953fd7b9f7bSTejun Heo 954fd7b9f7bSTejun Heo /* Relationship between s_mode and the DT_xxx types */ 955324a56e1STejun Heo static inline unsigned char dt_type(struct kernfs_node *kn) 956fd7b9f7bSTejun Heo { 957adc5e8b5STejun Heo return (kn->mode >> 12) & 15; 958fd7b9f7bSTejun Heo } 959fd7b9f7bSTejun Heo 960c637b8acSTejun Heo static int kernfs_dir_fop_release(struct inode *inode, struct file *filp) 961fd7b9f7bSTejun Heo { 962fd7b9f7bSTejun Heo kernfs_put(filp->private_data); 963fd7b9f7bSTejun Heo return 0; 964fd7b9f7bSTejun Heo } 965fd7b9f7bSTejun Heo 966c637b8acSTejun Heo static struct kernfs_node *kernfs_dir_pos(const void *ns, 967324a56e1STejun Heo struct kernfs_node *parent, loff_t hash, struct kernfs_node *pos) 968fd7b9f7bSTejun Heo { 969fd7b9f7bSTejun Heo if (pos) { 970ae34372eSTejun Heo int valid = pos->parent == parent && hash == pos->hash; 971fd7b9f7bSTejun Heo kernfs_put(pos); 972fd7b9f7bSTejun Heo if (!valid) 973fd7b9f7bSTejun Heo pos = NULL; 974fd7b9f7bSTejun Heo } 975fd7b9f7bSTejun Heo if (!pos && (hash > 1) && (hash < INT_MAX)) { 976adc5e8b5STejun Heo struct rb_node *node = parent->dir.children.rb_node; 977fd7b9f7bSTejun Heo while (node) { 978324a56e1STejun Heo pos = rb_to_kn(node); 979fd7b9f7bSTejun Heo 980adc5e8b5STejun Heo if (hash < pos->hash) 981fd7b9f7bSTejun Heo node = node->rb_left; 982adc5e8b5STejun Heo else if (hash > pos->hash) 983fd7b9f7bSTejun Heo node = node->rb_right; 984fd7b9f7bSTejun Heo else 985fd7b9f7bSTejun Heo break; 986fd7b9f7bSTejun Heo } 987fd7b9f7bSTejun Heo } 988fd7b9f7bSTejun Heo /* Skip over entries in the wrong namespace */ 989adc5e8b5STejun Heo while (pos && pos->ns != ns) { 990adc5e8b5STejun Heo struct rb_node *node = rb_next(&pos->rb); 991fd7b9f7bSTejun Heo if (!node) 992fd7b9f7bSTejun Heo pos = NULL; 993fd7b9f7bSTejun Heo else 994324a56e1STejun Heo pos = rb_to_kn(node); 995fd7b9f7bSTejun Heo } 996fd7b9f7bSTejun Heo return pos; 997fd7b9f7bSTejun Heo } 998fd7b9f7bSTejun Heo 999c637b8acSTejun Heo static struct kernfs_node *kernfs_dir_next_pos(const void *ns, 1000324a56e1STejun Heo struct kernfs_node *parent, ino_t ino, struct kernfs_node *pos) 1001fd7b9f7bSTejun Heo { 1002c637b8acSTejun Heo pos = kernfs_dir_pos(ns, parent, ino, pos); 1003fd7b9f7bSTejun Heo if (pos) 1004fd7b9f7bSTejun Heo do { 1005adc5e8b5STejun Heo struct rb_node *node = rb_next(&pos->rb); 1006fd7b9f7bSTejun Heo if (!node) 1007fd7b9f7bSTejun Heo pos = NULL; 1008fd7b9f7bSTejun Heo else 1009324a56e1STejun Heo pos = rb_to_kn(node); 1010adc5e8b5STejun Heo } while (pos && pos->ns != ns); 1011fd7b9f7bSTejun Heo return pos; 1012fd7b9f7bSTejun Heo } 1013fd7b9f7bSTejun Heo 1014c637b8acSTejun Heo static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx) 1015fd7b9f7bSTejun Heo { 1016fd7b9f7bSTejun Heo struct dentry *dentry = file->f_path.dentry; 1017324a56e1STejun Heo struct kernfs_node *parent = dentry->d_fsdata; 1018324a56e1STejun Heo struct kernfs_node *pos = file->private_data; 1019fd7b9f7bSTejun Heo const void *ns = NULL; 1020fd7b9f7bSTejun Heo 1021fd7b9f7bSTejun Heo if (!dir_emit_dots(file, ctx)) 1022fd7b9f7bSTejun Heo return 0; 1023a797bfc3STejun Heo mutex_lock(&kernfs_mutex); 1024fd7b9f7bSTejun Heo 1025324a56e1STejun Heo if (kernfs_ns_enabled(parent)) 1026c525aaddSTejun Heo ns = kernfs_info(dentry->d_sb)->ns; 1027fd7b9f7bSTejun Heo 1028c637b8acSTejun Heo for (pos = kernfs_dir_pos(ns, parent, ctx->pos, pos); 1029fd7b9f7bSTejun Heo pos; 1030c637b8acSTejun Heo pos = kernfs_dir_next_pos(ns, parent, ctx->pos, pos)) { 1031adc5e8b5STejun Heo const char *name = pos->name; 1032fd7b9f7bSTejun Heo unsigned int type = dt_type(pos); 1033fd7b9f7bSTejun Heo int len = strlen(name); 1034adc5e8b5STejun Heo ino_t ino = pos->ino; 1035fd7b9f7bSTejun Heo 1036adc5e8b5STejun Heo ctx->pos = pos->hash; 1037fd7b9f7bSTejun Heo file->private_data = pos; 1038fd7b9f7bSTejun Heo kernfs_get(pos); 1039fd7b9f7bSTejun Heo 1040a797bfc3STejun Heo mutex_unlock(&kernfs_mutex); 1041fd7b9f7bSTejun Heo if (!dir_emit(ctx, name, len, ino, type)) 1042fd7b9f7bSTejun Heo return 0; 1043a797bfc3STejun Heo mutex_lock(&kernfs_mutex); 1044fd7b9f7bSTejun Heo } 1045a797bfc3STejun Heo mutex_unlock(&kernfs_mutex); 1046fd7b9f7bSTejun Heo file->private_data = NULL; 1047fd7b9f7bSTejun Heo ctx->pos = INT_MAX; 1048fd7b9f7bSTejun Heo return 0; 1049fd7b9f7bSTejun Heo } 1050fd7b9f7bSTejun Heo 1051c637b8acSTejun Heo static loff_t kernfs_dir_fop_llseek(struct file *file, loff_t offset, 1052c637b8acSTejun Heo int whence) 1053fd7b9f7bSTejun Heo { 1054fd7b9f7bSTejun Heo struct inode *inode = file_inode(file); 1055fd7b9f7bSTejun Heo loff_t ret; 1056fd7b9f7bSTejun Heo 1057fd7b9f7bSTejun Heo mutex_lock(&inode->i_mutex); 1058fd7b9f7bSTejun Heo ret = generic_file_llseek(file, offset, whence); 1059fd7b9f7bSTejun Heo mutex_unlock(&inode->i_mutex); 1060fd7b9f7bSTejun Heo 1061fd7b9f7bSTejun Heo return ret; 1062fd7b9f7bSTejun Heo } 1063fd7b9f7bSTejun Heo 1064a797bfc3STejun Heo const struct file_operations kernfs_dir_fops = { 1065fd7b9f7bSTejun Heo .read = generic_read_dir, 1066c637b8acSTejun Heo .iterate = kernfs_fop_readdir, 1067c637b8acSTejun Heo .release = kernfs_dir_fop_release, 1068c637b8acSTejun Heo .llseek = kernfs_dir_fop_llseek, 1069fd7b9f7bSTejun Heo }; 1070