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 * 267063fbf2SJoel Becker * Please see Documentation/filesystems/configfs.txt for more information. 277063fbf2SJoel Becker */ 287063fbf2SJoel Becker 297063fbf2SJoel Becker #undef DEBUG 307063fbf2SJoel Becker 317063fbf2SJoel Becker #include <linux/pagemap.h> 327063fbf2SJoel Becker #include <linux/namei.h> 337063fbf2SJoel Becker #include <linux/backing-dev.h> 343d0f89bbSJoel Becker #include <linux/capability.h> 35e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 36e74cc06dSLouis Rilling #include <linux/lockdep.h> 377063fbf2SJoel Becker 387063fbf2SJoel Becker #include <linux/configfs.h> 397063fbf2SJoel Becker #include "configfs_internal.h" 407063fbf2SJoel Becker 41e74cc06dSLouis Rilling #ifdef CONFIG_LOCKDEP 42e74cc06dSLouis Rilling static struct lock_class_key default_group_class[MAX_LOCK_DEPTH]; 43e74cc06dSLouis Rilling #endif 44e74cc06dSLouis Rilling 457063fbf2SJoel Becker extern struct super_block * configfs_sb; 467063fbf2SJoel Becker 47f5e54d6eSChristoph Hellwig static const struct address_space_operations configfs_aops = { 487063fbf2SJoel Becker .readpage = simple_readpage, 49800d15a5SNick Piggin .write_begin = simple_write_begin, 50800d15a5SNick Piggin .write_end = simple_write_end, 517063fbf2SJoel Becker }; 527063fbf2SJoel Becker 537063fbf2SJoel Becker static struct backing_dev_info configfs_backing_dev_info = { 54d993831fSJens Axboe .name = "configfs", 557063fbf2SJoel Becker .ra_pages = 0, /* No readahead */ 56e4ad08feSMiklos Szeredi .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, 577063fbf2SJoel Becker }; 587063fbf2SJoel Becker 59754661f1SArjan van de Ven static const struct inode_operations configfs_inode_operations ={ 603d0f89bbSJoel Becker .setattr = configfs_setattr, 613d0f89bbSJoel Becker }; 623d0f89bbSJoel Becker 633d0f89bbSJoel Becker int configfs_setattr(struct dentry * dentry, struct iattr * iattr) 647063fbf2SJoel Becker { 653d0f89bbSJoel Becker struct inode * inode = dentry->d_inode; 663d0f89bbSJoel Becker struct configfs_dirent * sd = dentry->d_fsdata; 673d0f89bbSJoel Becker struct iattr * sd_iattr; 683d0f89bbSJoel Becker unsigned int ia_valid = iattr->ia_valid; 693d0f89bbSJoel Becker int error; 703d0f89bbSJoel Becker 713d0f89bbSJoel Becker if (!sd) 723d0f89bbSJoel Becker return -EINVAL; 733d0f89bbSJoel Becker 743d0f89bbSJoel Becker sd_iattr = sd->s_iattr; 753d0f89bbSJoel Becker 763d0f89bbSJoel Becker error = inode_change_ok(inode, iattr); 773d0f89bbSJoel Becker if (error) 783d0f89bbSJoel Becker return error; 793d0f89bbSJoel Becker 803d0f89bbSJoel Becker error = inode_setattr(inode, iattr); 813d0f89bbSJoel Becker if (error) 823d0f89bbSJoel Becker return error; 833d0f89bbSJoel Becker 843d0f89bbSJoel Becker if (!sd_iattr) { 853d0f89bbSJoel Becker /* setting attributes for the first time, allocate now */ 86f8314dc6SPanagiotis Issaris sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL); 873d0f89bbSJoel Becker if (!sd_iattr) 883d0f89bbSJoel Becker return -ENOMEM; 893d0f89bbSJoel Becker /* assign default attributes */ 903d0f89bbSJoel Becker sd_iattr->ia_mode = sd->s_mode; 913d0f89bbSJoel Becker sd_iattr->ia_uid = 0; 923d0f89bbSJoel Becker sd_iattr->ia_gid = 0; 933d0f89bbSJoel Becker sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME; 943d0f89bbSJoel Becker sd->s_iattr = sd_iattr; 953d0f89bbSJoel Becker } 963d0f89bbSJoel Becker 973d0f89bbSJoel Becker /* attributes were changed atleast once in past */ 983d0f89bbSJoel Becker 993d0f89bbSJoel Becker if (ia_valid & ATTR_UID) 1003d0f89bbSJoel Becker sd_iattr->ia_uid = iattr->ia_uid; 1013d0f89bbSJoel Becker if (ia_valid & ATTR_GID) 1023d0f89bbSJoel Becker sd_iattr->ia_gid = iattr->ia_gid; 1033d0f89bbSJoel Becker if (ia_valid & ATTR_ATIME) 1043d0f89bbSJoel Becker sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime, 1053d0f89bbSJoel Becker inode->i_sb->s_time_gran); 1063d0f89bbSJoel Becker if (ia_valid & ATTR_MTIME) 1073d0f89bbSJoel Becker sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime, 1083d0f89bbSJoel Becker inode->i_sb->s_time_gran); 1093d0f89bbSJoel Becker if (ia_valid & ATTR_CTIME) 1103d0f89bbSJoel Becker sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime, 1113d0f89bbSJoel Becker inode->i_sb->s_time_gran); 1123d0f89bbSJoel Becker if (ia_valid & ATTR_MODE) { 1133d0f89bbSJoel Becker umode_t mode = iattr->ia_mode; 1143d0f89bbSJoel Becker 1153d0f89bbSJoel Becker if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 1163d0f89bbSJoel Becker mode &= ~S_ISGID; 1173d0f89bbSJoel Becker sd_iattr->ia_mode = sd->s_mode = mode; 1183d0f89bbSJoel Becker } 1193d0f89bbSJoel Becker 1203d0f89bbSJoel Becker return error; 1213d0f89bbSJoel Becker } 1223d0f89bbSJoel Becker 1233d0f89bbSJoel Becker static inline void set_default_inode_attr(struct inode * inode, mode_t mode) 1243d0f89bbSJoel Becker { 1257063fbf2SJoel Becker inode->i_mode = mode; 1263d0f89bbSJoel Becker inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 1273d0f89bbSJoel Becker } 1283d0f89bbSJoel Becker 1293d0f89bbSJoel Becker static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) 1303d0f89bbSJoel Becker { 1313d0f89bbSJoel Becker inode->i_mode = iattr->ia_mode; 1323d0f89bbSJoel Becker inode->i_uid = iattr->ia_uid; 1333d0f89bbSJoel Becker inode->i_gid = iattr->ia_gid; 1343d0f89bbSJoel Becker inode->i_atime = iattr->ia_atime; 1353d0f89bbSJoel Becker inode->i_mtime = iattr->ia_mtime; 1363d0f89bbSJoel Becker inode->i_ctime = iattr->ia_ctime; 1373d0f89bbSJoel Becker } 1383d0f89bbSJoel Becker 1393d0f89bbSJoel Becker struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd) 1403d0f89bbSJoel Becker { 1413d0f89bbSJoel Becker struct inode * inode = new_inode(configfs_sb); 1423d0f89bbSJoel Becker if (inode) { 1437063fbf2SJoel Becker inode->i_mapping->a_ops = &configfs_aops; 1447063fbf2SJoel Becker inode->i_mapping->backing_dev_info = &configfs_backing_dev_info; 1453d0f89bbSJoel Becker inode->i_op = &configfs_inode_operations; 1463d0f89bbSJoel Becker 1473d0f89bbSJoel Becker if (sd->s_iattr) { 1483d0f89bbSJoel Becker /* sysfs_dirent has non-default attributes 1493d0f89bbSJoel Becker * get them for the new inode from persistent copy 1503d0f89bbSJoel Becker * in sysfs_dirent 1513d0f89bbSJoel Becker */ 1523d0f89bbSJoel Becker set_inode_attr(inode, sd->s_iattr); 1533d0f89bbSJoel Becker } else 1543d0f89bbSJoel Becker set_default_inode_attr(inode, mode); 1557063fbf2SJoel Becker } 1567063fbf2SJoel Becker return inode; 1577063fbf2SJoel Becker } 1587063fbf2SJoel Becker 159e74cc06dSLouis Rilling #ifdef CONFIG_LOCKDEP 160e74cc06dSLouis Rilling 161e74cc06dSLouis Rilling static void configfs_set_inode_lock_class(struct configfs_dirent *sd, 162e74cc06dSLouis Rilling struct inode *inode) 163e74cc06dSLouis Rilling { 164e74cc06dSLouis Rilling int depth = sd->s_depth; 165e74cc06dSLouis Rilling 166e74cc06dSLouis Rilling if (depth > 0) { 167e74cc06dSLouis Rilling if (depth <= ARRAY_SIZE(default_group_class)) { 168e74cc06dSLouis Rilling lockdep_set_class(&inode->i_mutex, 169e74cc06dSLouis Rilling &default_group_class[depth - 1]); 170e74cc06dSLouis Rilling } else { 171e74cc06dSLouis Rilling /* 172e74cc06dSLouis Rilling * In practice the maximum level of locking depth is 173e74cc06dSLouis Rilling * already reached. Just inform about possible reasons. 174e74cc06dSLouis Rilling */ 175e74cc06dSLouis Rilling printk(KERN_INFO "configfs: Too many levels of inodes" 176e74cc06dSLouis Rilling " for the locking correctness validator.\n"); 177e74cc06dSLouis Rilling printk(KERN_INFO "Spurious warnings may appear.\n"); 178e74cc06dSLouis Rilling } 179e74cc06dSLouis Rilling } 180e74cc06dSLouis Rilling } 181e74cc06dSLouis Rilling 182e74cc06dSLouis Rilling #else /* CONFIG_LOCKDEP */ 183e74cc06dSLouis Rilling 184e74cc06dSLouis Rilling static void configfs_set_inode_lock_class(struct configfs_dirent *sd, 185e74cc06dSLouis Rilling struct inode *inode) 186e74cc06dSLouis Rilling { 187e74cc06dSLouis Rilling } 188e74cc06dSLouis Rilling 189e74cc06dSLouis Rilling #endif /* CONFIG_LOCKDEP */ 190e74cc06dSLouis Rilling 1917063fbf2SJoel Becker int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) 1927063fbf2SJoel Becker { 1937063fbf2SJoel Becker int error = 0; 1947063fbf2SJoel Becker struct inode * inode = NULL; 1957063fbf2SJoel Becker if (dentry) { 1967063fbf2SJoel Becker if (!dentry->d_inode) { 1973d0f89bbSJoel Becker struct configfs_dirent *sd = dentry->d_fsdata; 1983d0f89bbSJoel Becker if ((inode = configfs_new_inode(mode, sd))) { 1997063fbf2SJoel Becker if (dentry->d_parent && dentry->d_parent->d_inode) { 2007063fbf2SJoel Becker struct inode *p_inode = dentry->d_parent->d_inode; 2017063fbf2SJoel Becker p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 2027063fbf2SJoel Becker } 203e74cc06dSLouis Rilling configfs_set_inode_lock_class(sd, inode); 2047063fbf2SJoel Becker goto Proceed; 2057063fbf2SJoel Becker } 2067063fbf2SJoel Becker else 2077063fbf2SJoel Becker error = -ENOMEM; 2087063fbf2SJoel Becker } else 2097063fbf2SJoel Becker error = -EEXIST; 2107063fbf2SJoel Becker } else 2117063fbf2SJoel Becker error = -ENOENT; 2127063fbf2SJoel Becker goto Done; 2137063fbf2SJoel Becker 2147063fbf2SJoel Becker Proceed: 2157063fbf2SJoel Becker if (init) 2167063fbf2SJoel Becker error = init(inode); 2177063fbf2SJoel Becker if (!error) { 2187063fbf2SJoel Becker d_instantiate(dentry, inode); 2197063fbf2SJoel Becker if (S_ISDIR(mode) || S_ISLNK(mode)) 2207063fbf2SJoel Becker dget(dentry); /* pin link and directory dentries in core */ 2217063fbf2SJoel Becker } else 2227063fbf2SJoel Becker iput(inode); 2237063fbf2SJoel Becker Done: 2247063fbf2SJoel Becker return error; 2257063fbf2SJoel Becker } 2267063fbf2SJoel Becker 2277063fbf2SJoel Becker /* 2287063fbf2SJoel Becker * Get the name for corresponding element represented by the given configfs_dirent 2297063fbf2SJoel Becker */ 2307063fbf2SJoel Becker const unsigned char * configfs_get_name(struct configfs_dirent *sd) 2317063fbf2SJoel Becker { 2323d0f89bbSJoel Becker struct configfs_attribute *attr; 2337063fbf2SJoel Becker 2341a1974fdSEric Sesterhenn / snakebyte BUG_ON(!sd || !sd->s_element); 2357063fbf2SJoel Becker 2367063fbf2SJoel Becker /* These always have a dentry, so use that */ 2377063fbf2SJoel Becker if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK)) 2387063fbf2SJoel Becker return sd->s_dentry->d_name.name; 2397063fbf2SJoel Becker 2407063fbf2SJoel Becker if (sd->s_type & CONFIGFS_ITEM_ATTR) { 2417063fbf2SJoel Becker attr = sd->s_element; 2423d0f89bbSJoel Becker return attr->ca_name; 2437063fbf2SJoel Becker } 2447063fbf2SJoel Becker return NULL; 2457063fbf2SJoel Becker } 2467063fbf2SJoel Becker 2477063fbf2SJoel Becker 2487063fbf2SJoel Becker /* 2497063fbf2SJoel Becker * Unhashes the dentry corresponding to given configfs_dirent 2501b1dcc1bSJes Sorensen * Called with parent inode's i_mutex held. 2517063fbf2SJoel Becker */ 2527063fbf2SJoel Becker void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent) 2537063fbf2SJoel Becker { 2547063fbf2SJoel Becker struct dentry * dentry = sd->s_dentry; 2557063fbf2SJoel Becker 2567063fbf2SJoel Becker if (dentry) { 2577063fbf2SJoel Becker spin_lock(&dcache_lock); 2583d0f89bbSJoel Becker spin_lock(&dentry->d_lock); 2597063fbf2SJoel Becker if (!(d_unhashed(dentry) && dentry->d_inode)) { 2607063fbf2SJoel Becker dget_locked(dentry); 2617063fbf2SJoel Becker __d_drop(dentry); 2623d0f89bbSJoel Becker spin_unlock(&dentry->d_lock); 2637063fbf2SJoel Becker spin_unlock(&dcache_lock); 2647063fbf2SJoel Becker simple_unlink(parent->d_inode, dentry); 2653d0f89bbSJoel Becker } else { 2663d0f89bbSJoel Becker spin_unlock(&dentry->d_lock); 2677063fbf2SJoel Becker spin_unlock(&dcache_lock); 2687063fbf2SJoel Becker } 2697063fbf2SJoel Becker } 2703d0f89bbSJoel Becker } 2717063fbf2SJoel Becker 2727063fbf2SJoel Becker void configfs_hash_and_remove(struct dentry * dir, const char * name) 2737063fbf2SJoel Becker { 2747063fbf2SJoel Becker struct configfs_dirent * sd; 2757063fbf2SJoel Becker struct configfs_dirent * parent_sd = dir->d_fsdata; 2767063fbf2SJoel Becker 2773d0f89bbSJoel Becker if (dir->d_inode == NULL) 2783d0f89bbSJoel Becker /* no inode means this hasn't been made visible yet */ 2793d0f89bbSJoel Becker return; 2803d0f89bbSJoel Becker 2811b1dcc1bSJes Sorensen mutex_lock(&dir->d_inode->i_mutex); 2827063fbf2SJoel Becker list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 2837063fbf2SJoel Becker if (!sd->s_element) 2847063fbf2SJoel Becker continue; 2857063fbf2SJoel Becker if (!strcmp(configfs_get_name(sd), name)) { 2866f610764SLouis Rilling spin_lock(&configfs_dirent_lock); 2877063fbf2SJoel Becker list_del_init(&sd->s_sibling); 2886f610764SLouis Rilling spin_unlock(&configfs_dirent_lock); 2897063fbf2SJoel Becker configfs_drop_dentry(sd, dir); 2907063fbf2SJoel Becker configfs_put(sd); 2917063fbf2SJoel Becker break; 2927063fbf2SJoel Becker } 2937063fbf2SJoel Becker } 2941b1dcc1bSJes Sorensen mutex_unlock(&dir->d_inode->i_mutex); 2957063fbf2SJoel Becker } 2967063fbf2SJoel Becker 297e0bf68ddSPeter Zijlstra int __init configfs_inode_init(void) 298e0bf68ddSPeter Zijlstra { 299e0bf68ddSPeter Zijlstra return bdi_init(&configfs_backing_dev_info); 300e0bf68ddSPeter Zijlstra } 3017063fbf2SJoel Becker 302e0bf68ddSPeter Zijlstra void __exit configfs_inode_exit(void) 303e0bf68ddSPeter Zijlstra { 304e0bf68ddSPeter Zijlstra bdi_destroy(&configfs_backing_dev_info); 305e0bf68ddSPeter Zijlstra } 306