17063fbf2SJoel Becker /* -*- mode: c; c-basic-offset: 8; -*- 27063fbf2SJoel Becker * vim: noexpandtab sw=8 ts=8 sts=0: 37063fbf2SJoel Becker * 47063fbf2SJoel Becker * inode.c - basic inode and dentry operations. 57063fbf2SJoel Becker * 67063fbf2SJoel Becker * This program is free software; you can redistribute it and/or 77063fbf2SJoel Becker * modify it under the terms of the GNU General Public 87063fbf2SJoel Becker * License as published by the Free Software Foundation; either 97063fbf2SJoel Becker * version 2 of the License, or (at your option) any later version. 107063fbf2SJoel Becker * 117063fbf2SJoel Becker * This program is distributed in the hope that it will be useful, 127063fbf2SJoel Becker * but WITHOUT ANY WARRANTY; without even the implied warranty of 137063fbf2SJoel Becker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 147063fbf2SJoel Becker * General Public License for more details. 157063fbf2SJoel Becker * 167063fbf2SJoel Becker * You should have received a copy of the GNU General Public 177063fbf2SJoel Becker * License along with this program; if not, write to the 187063fbf2SJoel Becker * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 197063fbf2SJoel Becker * Boston, MA 021110-1307, USA. 207063fbf2SJoel Becker * 217063fbf2SJoel Becker * Based on sysfs: 227063fbf2SJoel Becker * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 237063fbf2SJoel Becker * 247063fbf2SJoel Becker * configfs Copyright (C) 2005 Oracle. All rights reserved. 257063fbf2SJoel Becker * 26395cf969SPaul Bolle * Please see Documentation/filesystems/configfs/configfs.txt for more 27395cf969SPaul Bolle * information. 287063fbf2SJoel Becker */ 297063fbf2SJoel Becker 307063fbf2SJoel Becker #undef DEBUG 317063fbf2SJoel Becker 327063fbf2SJoel Becker #include <linux/pagemap.h> 337063fbf2SJoel Becker #include <linux/namei.h> 347063fbf2SJoel Becker #include <linux/backing-dev.h> 353d0f89bbSJoel Becker #include <linux/capability.h> 36e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 37e74cc06dSLouis Rilling #include <linux/lockdep.h> 385a0e3ad6STejun Heo #include <linux/slab.h> 397063fbf2SJoel Becker 407063fbf2SJoel Becker #include <linux/configfs.h> 417063fbf2SJoel Becker #include "configfs_internal.h" 427063fbf2SJoel Becker 43e74cc06dSLouis Rilling #ifdef CONFIG_LOCKDEP 44e74cc06dSLouis Rilling static struct lock_class_key default_group_class[MAX_LOCK_DEPTH]; 45e74cc06dSLouis Rilling #endif 46e74cc06dSLouis Rilling 477063fbf2SJoel Becker extern struct super_block * configfs_sb; 487063fbf2SJoel Becker 49f5e54d6eSChristoph Hellwig static const struct address_space_operations configfs_aops = { 507063fbf2SJoel Becker .readpage = simple_readpage, 51800d15a5SNick Piggin .write_begin = simple_write_begin, 52800d15a5SNick Piggin .write_end = simple_write_end, 537063fbf2SJoel Becker }; 547063fbf2SJoel Becker 557063fbf2SJoel Becker static struct backing_dev_info configfs_backing_dev_info = { 56d993831fSJens Axboe .name = "configfs", 577063fbf2SJoel Becker .ra_pages = 0, /* No readahead */ 58e4ad08feSMiklos Szeredi .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, 597063fbf2SJoel Becker }; 607063fbf2SJoel Becker 61754661f1SArjan van de Ven static const struct inode_operations configfs_inode_operations ={ 623d0f89bbSJoel Becker .setattr = configfs_setattr, 633d0f89bbSJoel Becker }; 643d0f89bbSJoel Becker 653d0f89bbSJoel Becker int configfs_setattr(struct dentry * dentry, struct iattr * iattr) 667063fbf2SJoel Becker { 673d0f89bbSJoel Becker struct inode * inode = dentry->d_inode; 683d0f89bbSJoel Becker struct configfs_dirent * sd = dentry->d_fsdata; 693d0f89bbSJoel Becker struct iattr * sd_iattr; 703d0f89bbSJoel Becker unsigned int ia_valid = iattr->ia_valid; 713d0f89bbSJoel Becker int error; 723d0f89bbSJoel Becker 733d0f89bbSJoel Becker if (!sd) 743d0f89bbSJoel Becker return -EINVAL; 753d0f89bbSJoel Becker 763d0f89bbSJoel Becker sd_iattr = sd->s_iattr; 773d0f89bbSJoel Becker if (!sd_iattr) { 783d0f89bbSJoel Becker /* setting attributes for the first time, allocate now */ 79f8314dc6SPanagiotis Issaris sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL); 803d0f89bbSJoel Becker if (!sd_iattr) 813d0f89bbSJoel Becker return -ENOMEM; 823d0f89bbSJoel Becker /* assign default attributes */ 833d0f89bbSJoel Becker sd_iattr->ia_mode = sd->s_mode; 843d0f89bbSJoel Becker sd_iattr->ia_uid = 0; 853d0f89bbSJoel Becker sd_iattr->ia_gid = 0; 863d0f89bbSJoel Becker sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME; 873d0f89bbSJoel Becker sd->s_iattr = sd_iattr; 883d0f89bbSJoel Becker } 893d0f89bbSJoel Becker /* attributes were changed atleast once in past */ 903d0f89bbSJoel Becker 9175de46b9SNick Piggin error = simple_setattr(dentry, iattr); 9275de46b9SNick Piggin if (error) 9375de46b9SNick Piggin return error; 9475de46b9SNick Piggin 953d0f89bbSJoel Becker if (ia_valid & ATTR_UID) 963d0f89bbSJoel Becker sd_iattr->ia_uid = iattr->ia_uid; 973d0f89bbSJoel Becker if (ia_valid & ATTR_GID) 983d0f89bbSJoel Becker sd_iattr->ia_gid = iattr->ia_gid; 993d0f89bbSJoel Becker if (ia_valid & ATTR_ATIME) 1003d0f89bbSJoel Becker sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime, 1013d0f89bbSJoel Becker inode->i_sb->s_time_gran); 1023d0f89bbSJoel Becker if (ia_valid & ATTR_MTIME) 1033d0f89bbSJoel Becker sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime, 1043d0f89bbSJoel Becker inode->i_sb->s_time_gran); 1053d0f89bbSJoel Becker if (ia_valid & ATTR_CTIME) 1063d0f89bbSJoel Becker sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime, 1073d0f89bbSJoel Becker inode->i_sb->s_time_gran); 1083d0f89bbSJoel Becker if (ia_valid & ATTR_MODE) { 1093d0f89bbSJoel Becker umode_t mode = iattr->ia_mode; 1103d0f89bbSJoel Becker 1113d0f89bbSJoel Becker if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 1123d0f89bbSJoel Becker mode &= ~S_ISGID; 1133d0f89bbSJoel Becker sd_iattr->ia_mode = sd->s_mode = mode; 1143d0f89bbSJoel Becker } 1153d0f89bbSJoel Becker 1163d0f89bbSJoel Becker return error; 1173d0f89bbSJoel Becker } 1183d0f89bbSJoel Becker 1193d0f89bbSJoel Becker static inline void set_default_inode_attr(struct inode * inode, mode_t mode) 1203d0f89bbSJoel Becker { 1217063fbf2SJoel Becker inode->i_mode = mode; 1223d0f89bbSJoel Becker inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 1233d0f89bbSJoel Becker } 1243d0f89bbSJoel Becker 1253d0f89bbSJoel Becker static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) 1263d0f89bbSJoel Becker { 1273d0f89bbSJoel Becker inode->i_mode = iattr->ia_mode; 1283d0f89bbSJoel Becker inode->i_uid = iattr->ia_uid; 1293d0f89bbSJoel Becker inode->i_gid = iattr->ia_gid; 1303d0f89bbSJoel Becker inode->i_atime = iattr->ia_atime; 1313d0f89bbSJoel Becker inode->i_mtime = iattr->ia_mtime; 1323d0f89bbSJoel Becker inode->i_ctime = iattr->ia_ctime; 1333d0f89bbSJoel Becker } 1343d0f89bbSJoel Becker 1353d0f89bbSJoel Becker struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd) 1363d0f89bbSJoel Becker { 1373d0f89bbSJoel Becker struct inode * inode = new_inode(configfs_sb); 1383d0f89bbSJoel Becker if (inode) { 13985fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 1407063fbf2SJoel Becker inode->i_mapping->a_ops = &configfs_aops; 1417063fbf2SJoel Becker inode->i_mapping->backing_dev_info = &configfs_backing_dev_info; 1423d0f89bbSJoel Becker inode->i_op = &configfs_inode_operations; 1433d0f89bbSJoel Becker 1443d0f89bbSJoel Becker if (sd->s_iattr) { 1453d0f89bbSJoel Becker /* sysfs_dirent has non-default attributes 1463d0f89bbSJoel Becker * get them for the new inode from persistent copy 1473d0f89bbSJoel Becker * in sysfs_dirent 1483d0f89bbSJoel Becker */ 1493d0f89bbSJoel Becker set_inode_attr(inode, sd->s_iattr); 1503d0f89bbSJoel Becker } else 1513d0f89bbSJoel Becker set_default_inode_attr(inode, mode); 1527063fbf2SJoel Becker } 1537063fbf2SJoel Becker return inode; 1547063fbf2SJoel Becker } 1557063fbf2SJoel Becker 156e74cc06dSLouis Rilling #ifdef CONFIG_LOCKDEP 157e74cc06dSLouis Rilling 158e74cc06dSLouis Rilling static void configfs_set_inode_lock_class(struct configfs_dirent *sd, 159e74cc06dSLouis Rilling struct inode *inode) 160e74cc06dSLouis Rilling { 161e74cc06dSLouis Rilling int depth = sd->s_depth; 162e74cc06dSLouis Rilling 163e74cc06dSLouis Rilling if (depth > 0) { 164e74cc06dSLouis Rilling if (depth <= ARRAY_SIZE(default_group_class)) { 165e74cc06dSLouis Rilling lockdep_set_class(&inode->i_mutex, 166e74cc06dSLouis Rilling &default_group_class[depth - 1]); 167e74cc06dSLouis Rilling } else { 168e74cc06dSLouis Rilling /* 169e74cc06dSLouis Rilling * In practice the maximum level of locking depth is 170e74cc06dSLouis Rilling * already reached. Just inform about possible reasons. 171e74cc06dSLouis Rilling */ 172e74cc06dSLouis Rilling printk(KERN_INFO "configfs: Too many levels of inodes" 173e74cc06dSLouis Rilling " for the locking correctness validator.\n"); 174e74cc06dSLouis Rilling printk(KERN_INFO "Spurious warnings may appear.\n"); 175e74cc06dSLouis Rilling } 176e74cc06dSLouis Rilling } 177e74cc06dSLouis Rilling } 178e74cc06dSLouis Rilling 179e74cc06dSLouis Rilling #else /* CONFIG_LOCKDEP */ 180e74cc06dSLouis Rilling 181e74cc06dSLouis Rilling static void configfs_set_inode_lock_class(struct configfs_dirent *sd, 182e74cc06dSLouis Rilling struct inode *inode) 183e74cc06dSLouis Rilling { 184e74cc06dSLouis Rilling } 185e74cc06dSLouis Rilling 186e74cc06dSLouis Rilling #endif /* CONFIG_LOCKDEP */ 187e74cc06dSLouis Rilling 1887063fbf2SJoel Becker int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) 1897063fbf2SJoel Becker { 1907063fbf2SJoel Becker int error = 0; 1917063fbf2SJoel Becker struct inode * inode = NULL; 1927063fbf2SJoel Becker if (dentry) { 1937063fbf2SJoel Becker if (!dentry->d_inode) { 1943d0f89bbSJoel Becker struct configfs_dirent *sd = dentry->d_fsdata; 1953d0f89bbSJoel Becker if ((inode = configfs_new_inode(mode, sd))) { 1967063fbf2SJoel Becker if (dentry->d_parent && dentry->d_parent->d_inode) { 1977063fbf2SJoel Becker struct inode *p_inode = dentry->d_parent->d_inode; 1987063fbf2SJoel Becker p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 1997063fbf2SJoel Becker } 200e74cc06dSLouis Rilling configfs_set_inode_lock_class(sd, inode); 2017063fbf2SJoel Becker goto Proceed; 2027063fbf2SJoel Becker } 2037063fbf2SJoel Becker else 2047063fbf2SJoel Becker error = -ENOMEM; 2057063fbf2SJoel Becker } else 2067063fbf2SJoel Becker error = -EEXIST; 2077063fbf2SJoel Becker } else 2087063fbf2SJoel Becker error = -ENOENT; 2097063fbf2SJoel Becker goto Done; 2107063fbf2SJoel Becker 2117063fbf2SJoel Becker Proceed: 2127063fbf2SJoel Becker if (init) 2137063fbf2SJoel Becker error = init(inode); 2147063fbf2SJoel Becker if (!error) { 2157063fbf2SJoel Becker d_instantiate(dentry, inode); 2167063fbf2SJoel Becker if (S_ISDIR(mode) || S_ISLNK(mode)) 2177063fbf2SJoel Becker dget(dentry); /* pin link and directory dentries in core */ 2187063fbf2SJoel Becker } else 2197063fbf2SJoel Becker iput(inode); 2207063fbf2SJoel Becker Done: 2217063fbf2SJoel Becker return error; 2227063fbf2SJoel Becker } 2237063fbf2SJoel Becker 2247063fbf2SJoel Becker /* 2257063fbf2SJoel Becker * Get the name for corresponding element represented by the given configfs_dirent 2267063fbf2SJoel Becker */ 2277063fbf2SJoel Becker const unsigned char * configfs_get_name(struct configfs_dirent *sd) 2287063fbf2SJoel Becker { 2293d0f89bbSJoel Becker struct configfs_attribute *attr; 2307063fbf2SJoel Becker 2311a1974fdSEric Sesterhenn / snakebyte BUG_ON(!sd || !sd->s_element); 2327063fbf2SJoel Becker 2337063fbf2SJoel Becker /* These always have a dentry, so use that */ 2347063fbf2SJoel Becker if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK)) 2357063fbf2SJoel Becker return sd->s_dentry->d_name.name; 2367063fbf2SJoel Becker 2377063fbf2SJoel Becker if (sd->s_type & CONFIGFS_ITEM_ATTR) { 2387063fbf2SJoel Becker attr = sd->s_element; 2393d0f89bbSJoel Becker return attr->ca_name; 2407063fbf2SJoel Becker } 2417063fbf2SJoel Becker return NULL; 2427063fbf2SJoel Becker } 2437063fbf2SJoel Becker 2447063fbf2SJoel Becker 2457063fbf2SJoel Becker /* 2467063fbf2SJoel Becker * Unhashes the dentry corresponding to given configfs_dirent 2471b1dcc1bSJes Sorensen * Called with parent inode's i_mutex held. 2487063fbf2SJoel Becker */ 2497063fbf2SJoel Becker void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent) 2507063fbf2SJoel Becker { 2517063fbf2SJoel Becker struct dentry * dentry = sd->s_dentry; 2527063fbf2SJoel Becker 2537063fbf2SJoel Becker if (dentry) { 2543d0f89bbSJoel Becker spin_lock(&dentry->d_lock); 2557063fbf2SJoel Becker if (!(d_unhashed(dentry) && dentry->d_inode)) { 256dc0474beSNick Piggin dget_dlock(dentry); 2577063fbf2SJoel Becker __d_drop(dentry); 2583d0f89bbSJoel Becker spin_unlock(&dentry->d_lock); 2597063fbf2SJoel Becker simple_unlink(parent->d_inode, dentry); 260b5c84bf6SNick Piggin } else 2613d0f89bbSJoel Becker spin_unlock(&dentry->d_lock); 2627063fbf2SJoel Becker } 2633d0f89bbSJoel Becker } 2647063fbf2SJoel Becker 2657063fbf2SJoel Becker void configfs_hash_and_remove(struct dentry * dir, const char * name) 2667063fbf2SJoel Becker { 2677063fbf2SJoel Becker struct configfs_dirent * sd; 2687063fbf2SJoel Becker struct configfs_dirent * parent_sd = dir->d_fsdata; 2697063fbf2SJoel Becker 2703d0f89bbSJoel Becker if (dir->d_inode == NULL) 2713d0f89bbSJoel Becker /* no inode means this hasn't been made visible yet */ 2723d0f89bbSJoel Becker return; 2733d0f89bbSJoel Becker 2741b1dcc1bSJes Sorensen mutex_lock(&dir->d_inode->i_mutex); 2757063fbf2SJoel Becker list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 2767063fbf2SJoel Becker if (!sd->s_element) 2777063fbf2SJoel Becker continue; 2787063fbf2SJoel Becker if (!strcmp(configfs_get_name(sd), name)) { 2796f610764SLouis Rilling spin_lock(&configfs_dirent_lock); 2807063fbf2SJoel Becker list_del_init(&sd->s_sibling); 2816f610764SLouis Rilling spin_unlock(&configfs_dirent_lock); 2827063fbf2SJoel Becker configfs_drop_dentry(sd, dir); 2837063fbf2SJoel Becker configfs_put(sd); 2847063fbf2SJoel Becker break; 2857063fbf2SJoel Becker } 2867063fbf2SJoel Becker } 2871b1dcc1bSJes Sorensen mutex_unlock(&dir->d_inode->i_mutex); 2887063fbf2SJoel Becker } 2897063fbf2SJoel Becker 290e0bf68ddSPeter Zijlstra int __init configfs_inode_init(void) 291e0bf68ddSPeter Zijlstra { 292e0bf68ddSPeter Zijlstra return bdi_init(&configfs_backing_dev_info); 293e0bf68ddSPeter Zijlstra } 2947063fbf2SJoel Becker 295e0bf68ddSPeter Zijlstra void __exit configfs_inode_exit(void) 296e0bf68ddSPeter Zijlstra { 297e0bf68ddSPeter Zijlstra bdi_destroy(&configfs_backing_dev_info); 298e0bf68ddSPeter Zijlstra } 299