inode.c 7.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * inode.c - basic inode and dentry operations.
 *
 * sysfs is Copyright (c) 2001-3 Patrick Mochel
 *
 * Please see Documentation/filesystems/sysfs.txt for more information.
 */

#undef DEBUG 

#include <linux/pagemap.h>
#include <linux/namei.h>
#include <linux/backing-dev.h>
14
#include <linux/capability.h>
15
#include <linux/errno.h>
A
Alexey Dobriyan 已提交
16
#include <linux/sched.h>
17
#include <asm/semaphore.h>
L
Linus Torvalds 已提交
18 19 20 21
#include "sysfs.h"

extern struct super_block * sysfs_sb;

22
static const struct address_space_operations sysfs_aops = {
L
Linus Torvalds 已提交
23 24 25 26 27 28 29 30 31 32
	.readpage	= simple_readpage,
	.prepare_write	= simple_prepare_write,
	.commit_write	= simple_commit_write
};

static struct backing_dev_info sysfs_backing_dev_info = {
	.ra_pages	= 0,	/* No readahead */
	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};

33
static const struct inode_operations sysfs_inode_operations ={
34 35 36
	.setattr	= sysfs_setattr,
};

37 38 39 40 41 42 43 44 45 46
void sysfs_delete_inode(struct inode *inode)
{
	/* Free the shadowed directory inode operations */
	if (sysfs_is_shadowed_inode(inode)) {
		kfree(inode->i_op);
		inode->i_op = NULL;
	}
	return generic_delete_inode(inode);
}

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
{
	struct inode * inode = dentry->d_inode;
	struct sysfs_dirent * sd = dentry->d_fsdata;
	struct iattr * sd_iattr;
	unsigned int ia_valid = iattr->ia_valid;
	int error;

	if (!sd)
		return -EINVAL;

	sd_iattr = sd->s_iattr;

	error = inode_change_ok(inode, iattr);
	if (error)
		return error;

	error = inode_setattr(inode, iattr);
	if (error)
		return error;

	if (!sd_iattr) {
		/* setting attributes for the first time, allocate now */
70
		sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
		if (!sd_iattr)
			return -ENOMEM;
		/* assign default attributes */
		sd_iattr->ia_mode = sd->s_mode;
		sd_iattr->ia_uid = 0;
		sd_iattr->ia_gid = 0;
		sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
		sd->s_iattr = sd_iattr;
	}

	/* attributes were changed atleast once in past */

	if (ia_valid & ATTR_UID)
		sd_iattr->ia_uid = iattr->ia_uid;
	if (ia_valid & ATTR_GID)
		sd_iattr->ia_gid = iattr->ia_gid;
	if (ia_valid & ATTR_ATIME)
		sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
						inode->i_sb->s_time_gran);
	if (ia_valid & ATTR_MTIME)
		sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
						inode->i_sb->s_time_gran);
	if (ia_valid & ATTR_CTIME)
		sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
						inode->i_sb->s_time_gran);
	if (ia_valid & ATTR_MODE) {
		umode_t mode = iattr->ia_mode;

		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
			mode &= ~S_ISGID;
M
Maneesh Soni 已提交
101
		sd_iattr->ia_mode = sd->s_mode = mode;
102 103 104 105 106
	}

	return error;
}

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
{
	inode->i_mode = mode;
	inode->i_uid = 0;
	inode->i_gid = 0;
	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}

static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
{
	inode->i_mode = iattr->ia_mode;
	inode->i_uid = iattr->ia_uid;
	inode->i_gid = iattr->ia_gid;
	inode->i_atime = iattr->ia_atime;
	inode->i_mtime = iattr->ia_mtime;
	inode->i_ctime = iattr->ia_ctime;
}

125 126 127 128 129 130 131 132 133 134 135

/*
 * sysfs has a different i_mutex lock order behavior for i_mutex than other
 * filesystems; sysfs i_mutex is called in many places with subsystem locks
 * held. At the same time, many of the VFS locking rules do not apply to
 * sysfs at all (cross directory rename for example). To untangle this mess
 * (which gives false positives in lockdep), we're giving sysfs inodes their
 * own class for i_mutex.
 */
static struct lock_class_key sysfs_inode_imutex_key;

136
void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
L
Linus Torvalds 已提交
137
{
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
	inode->i_blocks = 0;
	inode->i_mapping->a_ops = &sysfs_aops;
	inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
	inode->i_op = &sysfs_inode_operations;
	inode->i_ino = sd->s_ino;
	lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);

	if (sd->s_iattr) {
		/* sysfs_dirent has non-default attributes
		 * get them for the new inode from persistent copy
		 * in sysfs_dirent
		 */
		set_inode_attr(inode, sd->s_iattr);
	} else
		set_default_inode_attr(inode, sd->s_mode);
}

/**
 *	sysfs_new_inode - allocate new inode for sysfs_dirent
 *	@sd: sysfs_dirent to allocate inode for
 *
 *	Allocate inode for @sd and initialize basics.
 *
 *	LOCKING:
 *	Kernel thread context (may sleep).
 *
 *	RETURNS:
 *	Pointer to allocated inode on success, NULL on failure.
 */
struct inode * sysfs_new_inode(struct sysfs_dirent *sd)
{
	struct inode *inode;

	inode = new_inode(sysfs_sb);
	if (inode)
		sysfs_init_inode(sd, inode);

L
Linus Torvalds 已提交
175 176 177
	return inode;
}

178 179 180 181 182 183 184 185 186 187 188
/**
 *	sysfs_instantiate - instantiate dentry
 *	@dentry: dentry to be instantiated
 *	@inode: inode associated with @sd
 *
 *	Instantiate @dentry with @inode.
 *
 *	LOCKING:
 *	None.
 */
void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
L
Linus Torvalds 已提交
189
{
190 191 192 193 194 195 196 197
	BUG_ON(!dentry || dentry->d_inode);

	if (dentry->d_parent && dentry->d_parent->d_inode) {
		struct inode *p_inode = dentry->d_parent->d_inode;
		p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
	}

	d_instantiate(dentry, inode);
L
Linus Torvalds 已提交
198 199
}

200 201 202 203 204 205 206 207 208 209 210 211 212
/**
 *	sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
 *	@sd: target sysfs_dirent
 *
 *	Drop dentry for @sd.  @sd must have been unlinked from its
 *	parent on entry to this function such that it can't be looked
 *	up anymore.
 *
 *	@sd->s_dentry which is protected with sysfs_lock points to the
 *	currently associated dentry but we're not holding a reference
 *	to it and racing with dput().  Grab dcache_lock and verify
 *	dentry before dropping it.  If @sd->s_dentry is NULL or dput()
 *	beats us, no need to bother.
L
Linus Torvalds 已提交
213
 */
214
void sysfs_drop_dentry(struct sysfs_dirent *sd)
L
Linus Torvalds 已提交
215
{
216 217 218
	struct dentry *dentry = NULL, *parent = NULL;
	struct inode *dir;
	struct timespec curtime;
L
Linus Torvalds 已提交
219

220 221 222 223 224 225
	/* We're not holding a reference to ->s_dentry dentry but the
	 * field will stay valid as long as sysfs_lock is held.
	 */
	spin_lock(&sysfs_lock);
	spin_lock(&dcache_lock);

226 227
	if (sd->s_dentry && sd->s_dentry->d_inode) {
		/* get dentry if it's there and dput() didn't kill it yet */
228
		dentry = dget_locked(sd->s_dentry);
229 230 231 232 233 234 235 236 237 238 239 240 241 242
		parent = dentry->d_parent;
	} else if (sd->s_parent->s_dentry->d_inode) {
		/* We need to update the parent even if dentry for the
		 * victim itself doesn't exist.
		 */
		parent = dget_locked(sd->s_parent->s_dentry);
	}

	/* drop */
	if (dentry) {
		spin_lock(&dentry->d_lock);
		__d_drop(dentry);
		spin_unlock(&dentry->d_lock);
	}
243 244 245 246

	spin_unlock(&dcache_lock);
	spin_unlock(&sysfs_lock);

247 248 249 250 251 252 253 254 255 256 257 258
	/* nothing to do if the parent isn't in dcache */
	if (!parent)
		return;

	/* adjust nlink and update timestamp */
	dir = parent->d_inode;
	mutex_lock(&dir->i_mutex);

	curtime = CURRENT_TIME;

	dir->i_ctime = dir->i_mtime = curtime;

L
Linus Torvalds 已提交
259
	if (dentry) {
260 261 262 263 264 265 266
		dentry->d_inode->i_ctime = curtime;
		drop_nlink(dentry->d_inode);
		if (sd->s_type & SYSFS_DIR) {
			drop_nlink(dentry->d_inode);
			drop_nlink(dir);
			/* XXX: unpin if directory, this will go away soon */
			dput(dentry);
L
Linus Torvalds 已提交
267
		}
268 269 270
	}

	mutex_unlock(&dir->i_mutex);
271

272 273
	/* bye bye */
	if (dentry)
274
		dput(dentry);
275 276
	else
		dput(parent);
L
Linus Torvalds 已提交
277 278
}

279
int sysfs_hash_and_remove(struct dentry * dir, const char * name)
L
Linus Torvalds 已提交
280 281
{
	struct sysfs_dirent * sd;
282
	struct sysfs_dirent * parent_sd;
283
	int found = 0;
284 285

	if (!dir)
286
		return -ENOENT;
L
Linus Torvalds 已提交
287

288 289
	if (dir->d_inode == NULL)
		/* no inode means this hasn't been made visible yet */
290
		return -ENOENT;
291

292
	parent_sd = dir->d_fsdata;
293
	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
L
Linus Torvalds 已提交
294
	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
295
		if (!sd->s_type)
L
Linus Torvalds 已提交
296
			continue;
T
Tejun Heo 已提交
297
		if (!strcmp(sd->s_name, name)) {
L
Linus Torvalds 已提交
298
			list_del_init(&sd->s_sibling);
299
			found = 1;
L
Linus Torvalds 已提交
300 301 302
			break;
		}
	}
303
	mutex_unlock(&dir->d_inode->i_mutex);
304

305 306 307
	if (!found)
		return -ENOENT;

308
	sysfs_drop_dentry(sd);
309 310
	sysfs_deactivate(sd);
	sysfs_put(sd);
311

312
	return 0;
L
Linus Torvalds 已提交
313
}