dir.c 21.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10
/*
 * dir.c - Operations for sysfs directories.
 */

#undef DEBUG

#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/module.h>
#include <linux/kobject.h>
11
#include <linux/namei.h>
12
#include <linux/idr.h>
13
#include <linux/completion.h>
14
#include <asm/semaphore.h>
L
Linus Torvalds 已提交
15 16 17
#include "sysfs.h"

DECLARE_RWSEM(sysfs_rename_sem);
18
spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED;
19
spinlock_t kobj_sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
L
Linus Torvalds 已提交
20

21 22 23
static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_IDA(sysfs_ino_ida);

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
/**
 *	sysfs_link_sibling - link sysfs_dirent into sibling list
 *	@sd: sysfs_dirent of interest
 *
 *	Link @sd into its sibling list which starts from
 *	sd->s_parent->s_children.
 *
 *	Locking:
 *	mutex_lock(sd->s_parent->dentry->d_inode->i_mutex)
 */
static void sysfs_link_sibling(struct sysfs_dirent *sd)
{
	struct sysfs_dirent *parent_sd = sd->s_parent;

	BUG_ON(sd->s_sibling);
	sd->s_sibling = parent_sd->s_children;
	parent_sd->s_children = sd;
}

/**
 *	sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
 *	@sd: sysfs_dirent of interest
 *
 *	Unlink @sd from its sibling list which starts from
 *	sd->s_parent->s_children.
 *
 *	Locking:
 *	mutex_lock(sd->s_parent->dentry->d_inode->i_mutex)
 */
static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
{
	struct sysfs_dirent **pos;

	for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) {
		if (*pos == sd) {
			*pos = sd->s_sibling;
			sd->s_sibling = NULL;
			break;
		}
	}
}

66 67 68 69 70 71 72 73 74 75 76 77
/**
 *	sysfs_get_active - get an active reference to sysfs_dirent
 *	@sd: sysfs_dirent to get an active reference to
 *
 *	Get an active reference of @sd.  This function is noop if @sd
 *	is NULL.
 *
 *	RETURNS:
 *	Pointer to @sd on success, NULL on failure.
 */
struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
{
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
	if (unlikely(!sd))
		return NULL;

	while (1) {
		int v, t;

		v = atomic_read(&sd->s_active);
		if (unlikely(v < 0))
			return NULL;

		t = atomic_cmpxchg(&sd->s_active, v, v + 1);
		if (likely(t == v))
			return sd;
		if (t < 0)
			return NULL;

		cpu_relax();
95 96 97 98 99 100 101 102 103 104 105 106
	}
}

/**
 *	sysfs_put_active - put an active reference to sysfs_dirent
 *	@sd: sysfs_dirent to put an active reference to
 *
 *	Put an active reference to @sd.  This function is noop if @sd
 *	is NULL.
 */
void sysfs_put_active(struct sysfs_dirent *sd)
{
107 108 109 110 111 112 113 114 115 116 117
	struct completion *cmpl;
	int v;

	if (unlikely(!sd))
		return;

	v = atomic_dec_return(&sd->s_active);
	if (likely(v != SD_DEACTIVATED_BIAS))
		return;

	/* atomic_dec_return() is a mb(), we'll always see the updated
118
	 * sd->s_sibling.
119
	 */
120
	cmpl = (void *)sd->s_sibling;
121
	complete(cmpl);
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 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
}

/**
 *	sysfs_get_active_two - get active references to sysfs_dirent and parent
 *	@sd: sysfs_dirent of interest
 *
 *	Get active reference to @sd and its parent.  Parent's active
 *	reference is grabbed first.  This function is noop if @sd is
 *	NULL.
 *
 *	RETURNS:
 *	Pointer to @sd on success, NULL on failure.
 */
struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
{
	if (sd) {
		if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
			return NULL;
		if (unlikely(!sysfs_get_active(sd))) {
			sysfs_put_active(sd->s_parent);
			return NULL;
		}
	}
	return sd;
}

/**
 *	sysfs_put_active_two - put active references to sysfs_dirent and parent
 *	@sd: sysfs_dirent of interest
 *
 *	Put active references to @sd and its parent.  This function is
 *	noop if @sd is NULL.
 */
void sysfs_put_active_two(struct sysfs_dirent *sd)
{
	if (sd) {
		sysfs_put_active(sd);
		sysfs_put_active(sd->s_parent);
	}
}

/**
 *	sysfs_deactivate - deactivate sysfs_dirent
 *	@sd: sysfs_dirent to deactivate
 *
167
 *	Deny new active references and drain existing ones.
168 169 170
 */
void sysfs_deactivate(struct sysfs_dirent *sd)
{
171 172
	DECLARE_COMPLETION_ONSTACK(wait);
	int v;
173

174
	BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
175
	sd->s_sibling = (void *)&wait;
176 177

	/* atomic_add_return() is a mb(), put_active() will always see
178
	 * the updated sd->s_sibling.
179
	 */
180 181 182 183 184
	v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);

	if (v != SD_DEACTIVATED_BIAS)
		wait_for_completion(&wait);

185
	sd->s_sibling = NULL;
186 187
}

T
Tejun Heo 已提交
188
static int sysfs_alloc_ino(ino_t *pino)
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
{
	int ino, rc;

 retry:
	spin_lock(&sysfs_ino_lock);
	rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
	spin_unlock(&sysfs_ino_lock);

	if (rc == -EAGAIN) {
		if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
			goto retry;
		rc = -ENOMEM;
	}

	*pino = ino;
	return rc;
}

static void sysfs_free_ino(ino_t ino)
{
	spin_lock(&sysfs_ino_lock);
	ida_remove(&sysfs_ino_ida, ino);
	spin_unlock(&sysfs_ino_lock);
}

214 215
void release_sysfs_dirent(struct sysfs_dirent * sd)
{
T
Tejun Heo 已提交
216 217 218 219 220
	struct sysfs_dirent *parent_sd;

 repeat:
	parent_sd = sd->s_parent;

221
	if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
222
		sysfs_put(sd->s_elem.symlink.target_sd);
223
	if (sysfs_type(sd) & SYSFS_COPY_NAME)
T
Tejun Heo 已提交
224
		kfree(sd->s_name);
225
	kfree(sd->s_iattr);
226
	sysfs_free_ino(sd->s_ino);
227
	kmem_cache_free(sysfs_dir_cachep, sd);
T
Tejun Heo 已提交
228 229 230 231

	sd = parent_sd;
	if (sd && atomic_dec_and_test(&sd->s_count))
		goto repeat;
232 233
}

L
Linus Torvalds 已提交
234 235 236 237 238
static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
{
	struct sysfs_dirent * sd = dentry->d_fsdata;

	if (sd) {
239 240 241 242 243 244 245 246 247 248 249 250 251
		/* sd->s_dentry is protected with sysfs_lock.  This
		 * allows sysfs_drop_dentry() to dereference it.
		 */
		spin_lock(&sysfs_lock);

		/* The dentry might have been deleted or another
		 * lookup could have happened updating sd->s_dentry to
		 * point the new dentry.  Ignore if it isn't pointing
		 * to this dentry.
		 */
		if (sd->s_dentry == dentry)
			sd->s_dentry = NULL;
		spin_unlock(&sysfs_lock);
L
Linus Torvalds 已提交
252 253 254 255 256 257 258 259 260
		sysfs_put(sd);
	}
	iput(inode);
}

static struct dentry_operations sysfs_dentry_ops = {
	.d_iput		= sysfs_d_iput,
};

261
struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
L
Linus Torvalds 已提交
262
{
T
Tejun Heo 已提交
263 264 265 266 267 268 269 270
	char *dup_name = NULL;
	struct sysfs_dirent *sd = NULL;

	if (type & SYSFS_COPY_NAME) {
		name = dup_name = kstrdup(name, GFP_KERNEL);
		if (!name)
			goto err_out;
	}
L
Linus Torvalds 已提交
271

272
	sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
L
Linus Torvalds 已提交
273
	if (!sd)
T
Tejun Heo 已提交
274
		goto err_out;
L
Linus Torvalds 已提交
275

T
Tejun Heo 已提交
276 277
	if (sysfs_alloc_ino(&sd->s_ino))
		goto err_out;
278

L
Linus Torvalds 已提交
279
	atomic_set(&sd->s_count, 1);
280
	atomic_set(&sd->s_active, 0);
281
	atomic_set(&sd->s_event, 1);
282

T
Tejun Heo 已提交
283
	sd->s_name = name;
284
	sd->s_mode = mode;
285
	sd->s_flags = type;
L
Linus Torvalds 已提交
286 287

	return sd;
T
Tejun Heo 已提交
288 289 290 291 292

 err_out:
	kfree(dup_name);
	kmem_cache_free(sysfs_dir_cachep, sd);
	return NULL;
L
Linus Torvalds 已提交
293 294
}

295 296 297 298 299 300 301 302 303 304 305 306 307
static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry)
{
	dentry->d_op = &sysfs_dentry_ops;
	dentry->d_fsdata = sysfs_get(sd);

	/* protect sd->s_dentry against sysfs_d_iput */
	spin_lock(&sysfs_lock);
	sd->s_dentry = dentry;
	spin_unlock(&sysfs_lock);

	d_rehash(dentry);
}

308 309
void sysfs_attach_dirent(struct sysfs_dirent *sd,
			 struct sysfs_dirent *parent_sd, struct dentry *dentry)
310
{
311 312
	if (dentry)
		sysfs_attach_dentry(sd, dentry);
313

T
Tejun Heo 已提交
314 315
	if (parent_sd) {
		sd->s_parent = sysfs_get(parent_sd);
316
		sysfs_link_sibling(sd);
T
Tejun Heo 已提交
317
	}
318 319
}

320 321 322 323 324 325
/**
 *	sysfs_find_dirent - find sysfs_dirent with the given name
 *	@parent_sd: sysfs_dirent to search under
 *	@name: name to look for
 *
 *	Look for sysfs_dirent with name @name under @parent_sd.
326
 *
327 328
 *	LOCKING:
 *	mutex_lock(parent->i_mutex)
329
 *
330 331
 *	RETURNS:
 *	Pointer to sysfs_dirent if found, NULL if not.
332
 */
333 334
struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
				       const unsigned char *name)
335
{
336 337 338 339 340 341 342
	struct sysfs_dirent *sd;

	for (sd = parent_sd->s_children; sd; sd = sd->s_sibling)
		if (sysfs_type(sd) && !strcmp(sd->s_name, name))
			return sd;
	return NULL;
}
343

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
/**
 *	sysfs_get_dirent - find and get sysfs_dirent with the given name
 *	@parent_sd: sysfs_dirent to search under
 *	@name: name to look for
 *
 *	Look for sysfs_dirent with name @name under @parent_sd and get
 *	it if found.
 *
 *	LOCKING:
 *	Kernel thread context (may sleep)
 *
 *	RETURNS:
 *	Pointer to sysfs_dirent if found, NULL if not.
 */
struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
				      const unsigned char *name)
{
	struct sysfs_dirent *sd;

	mutex_lock(&parent_sd->s_dentry->d_inode->i_mutex);
	sd = sysfs_find_dirent(parent_sd, name);
	sysfs_get(sd);
	mutex_unlock(&parent_sd->s_dentry->d_inode->i_mutex);

	return sd;
369 370
}

371 372
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
		      const char *name, struct sysfs_dirent **p_sd)
L
Linus Torvalds 已提交
373
{
374
	struct dentry *parent = parent_sd->s_dentry;
L
Linus Torvalds 已提交
375 376
	int error;
	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
377
	struct dentry *dentry;
378
	struct inode *inode;
379
	struct sysfs_dirent *sd;
L
Linus Torvalds 已提交
380

381 382
	mutex_lock(&parent->d_inode->i_mutex);

383
	/* allocate */
384 385 386 387 388 389 390
	dentry = lookup_one_len(name, parent, strlen(name));
	if (IS_ERR(dentry)) {
		error = PTR_ERR(dentry);
		goto out_unlock;
	}

	error = -EEXIST;
391
	if (dentry->d_inode)
392 393
		goto out_dput;

394
	error = -ENOMEM;
395
	sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
396
	if (!sd)
397
		goto out_drop;
398
	sd->s_elem.dir.kobj = kobj;
399

400
	inode = sysfs_get_inode(sd);
401
	if (!inode)
402 403
		goto out_sput;

404 405 406 407 408 409
	if (inode->i_state & I_NEW) {
		inode->i_op = &sysfs_dir_inode_operations;
		inode->i_fop = &sysfs_dir_operations;
		/* directory inodes start off with i_nlink == 2 (for ".") */
		inc_nlink(inode);
	}
410 411 412

	/* link in */
	error = -EEXIST;
413
	if (sysfs_find_dirent(parent_sd, name))
414 415 416
		goto out_iput;

	sysfs_instantiate(dentry, inode);
417
	inc_nlink(parent->d_inode);
418
	sysfs_attach_dirent(sd, parent_sd, dentry);
419

420
	*p_sd = sd;
421
	error = 0;
422
	goto out_unlock;	/* pin directory dentry in core */
423

424 425
 out_iput:
	iput(inode);
426 427 428 429 430 431 432 433
 out_sput:
	sysfs_put(sd);
 out_drop:
	d_drop(dentry);
 out_dput:
	dput(dentry);
 out_unlock:
	mutex_unlock(&parent->d_inode->i_mutex);
L
Linus Torvalds 已提交
434 435 436
	return error;
}

437 438
int sysfs_create_subdir(struct kobject *kobj, const char *name,
			struct sysfs_dirent **p_sd)
L
Linus Torvalds 已提交
439
{
440
	return create_dir(kobj, kobj->sd, name, p_sd);
L
Linus Torvalds 已提交
441 442 443 444 445
}

/**
 *	sysfs_create_dir - create a directory for an object.
 *	@kobj:		object we're creating directory for. 
446
 *	@shadow_parent:	parent object.
L
Linus Torvalds 已提交
447
 */
448 449
int sysfs_create_dir(struct kobject *kobj,
		     struct sysfs_dirent *shadow_parent_sd)
L
Linus Torvalds 已提交
450
{
451
	struct sysfs_dirent *parent_sd, *sd;
L
Linus Torvalds 已提交
452 453 454 455
	int error = 0;

	BUG_ON(!kobj);

456 457
	if (shadow_parent_sd)
		parent_sd = shadow_parent_sd;
458
	else if (kobj->parent)
459
		parent_sd = kobj->parent->sd;
L
Linus Torvalds 已提交
460
	else if (sysfs_mount && sysfs_mount->mnt_sb)
461
		parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
L
Linus Torvalds 已提交
462 463 464
	else
		return -EFAULT;

465
	error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);
L
Linus Torvalds 已提交
466
	if (!error)
467
		kobj->sd = sd;
L
Linus Torvalds 已提交
468 469 470 471 472 473 474 475
	return error;
}

static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
				struct nameidata *nd)
{
	struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
	struct sysfs_dirent * sd;
476
	struct bin_attribute *bin_attr;
477 478
	struct inode *inode;
	int found = 0;
L
Linus Torvalds 已提交
479

480
	for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
481
		if ((sysfs_type(sd) & SYSFS_NOT_PINNED) &&
482 483
		    !strcmp(sd->s_name, dentry->d_name.name)) {
			found = 1;
L
Linus Torvalds 已提交
484 485 486 487
			break;
		}
	}

488 489 490 491 492
	/* no such entry */
	if (!found)
		return NULL;

	/* attach dentry and inode */
493
	inode = sysfs_get_inode(sd);
494 495 496
	if (!inode)
		return ERR_PTR(-ENOMEM);

497 498
	if (inode->i_state & I_NEW) {
		/* initialize inode according to type */
499 500
		switch (sysfs_type(sd)) {
		case SYSFS_KOBJ_ATTR:
501 502
			inode->i_size = PAGE_SIZE;
			inode->i_fop = &sysfs_file_operations;
503 504 505
			break;
		case SYSFS_KOBJ_BIN_ATTR:
			bin_attr = sd->s_elem.bin_attr.bin_attr;
506 507
			inode->i_size = bin_attr->size;
			inode->i_fop = &bin_fops;
508 509
			break;
		case SYSFS_KOBJ_LINK:
510
			inode->i_op = &sysfs_symlink_inode_operations;
511 512 513 514
			break;
		default:
			BUG();
		}
515
	}
516 517 518 519 520

	sysfs_instantiate(dentry, inode);
	sysfs_attach_dentry(sd, dentry);

	return NULL;
L
Linus Torvalds 已提交
521 522
}

523
const struct inode_operations sysfs_dir_inode_operations = {
L
Linus Torvalds 已提交
524
	.lookup		= sysfs_lookup,
525
	.setattr	= sysfs_setattr,
L
Linus Torvalds 已提交
526 527
};

528
static void remove_dir(struct sysfs_dirent *sd)
L
Linus Torvalds 已提交
529
{
530
	struct dentry *parent = sd->s_parent->s_dentry;
L
Linus Torvalds 已提交
531

532
	mutex_lock(&parent->d_inode->i_mutex);
533

534
	sysfs_unlink_sibling(sd);
535
	sd->s_flags |= SYSFS_FLAG_REMOVED;
L
Linus Torvalds 已提交
536

537
	pr_debug(" o %s removing done\n", sd->s_name);
L
Linus Torvalds 已提交
538

539
	mutex_unlock(&parent->d_inode->i_mutex);
540

541
	sysfs_drop_dentry(sd);
542 543
	sysfs_deactivate(sd);
	sysfs_put(sd);
L
Linus Torvalds 已提交
544 545
}

546
void sysfs_remove_subdir(struct sysfs_dirent *sd)
L
Linus Torvalds 已提交
547
{
548
	remove_dir(sd);
L
Linus Torvalds 已提交
549 550 551
}


552
static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
L
Linus Torvalds 已提交
553
{
554 555
	struct sysfs_dirent *removed = NULL;
	struct sysfs_dirent **pos;
556
	struct dentry *dir;
L
Linus Torvalds 已提交
557

558
	if (!dir_sd)
L
Linus Torvalds 已提交
559 560
		return;

561 562 563 564 565
	dir = dir_sd->s_dentry;

	pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
	mutex_lock(&dir->d_inode->i_mutex);
	pos = &dir_sd->s_children;
566 567 568
	while (*pos) {
		struct sysfs_dirent *sd = *pos;

569
		if (sysfs_type(sd) && (sysfs_type(sd) & SYSFS_NOT_PINNED)) {
570
			sd->s_flags |= SYSFS_FLAG_REMOVED;
571 572 573 574 575
			*pos = sd->s_sibling;
			sd->s_sibling = removed;
			removed = sd;
		} else
			pos = &(*pos)->s_sibling;
L
Linus Torvalds 已提交
576
	}
577
	mutex_unlock(&dir->d_inode->i_mutex);
L
Linus Torvalds 已提交
578

579 580 581 582 583 584
	while (removed) {
		struct sysfs_dirent *sd = removed;

		removed = sd->s_sibling;
		sd->s_sibling = NULL;

585
		sysfs_drop_dentry(sd);
586 587 588 589
		sysfs_deactivate(sd);
		sysfs_put(sd);
	}

590
	remove_dir(dir_sd);
591 592 593 594 595 596 597 598 599 600 601 602 603
}

/**
 *	sysfs_remove_dir - remove an object's directory.
 *	@kobj:	object.
 *
 *	The only thing special about this is that we remove any files in
 *	the directory before we remove the directory, and we've inlined
 *	what used to be sysfs_rmdir() below, instead of calling separately.
 */

void sysfs_remove_dir(struct kobject * kobj)
{
604
	struct sysfs_dirent *sd = kobj->sd;
605 606

	spin_lock(&kobj_sysfs_assoc_lock);
607
	kobj->sd = NULL;
608 609
	spin_unlock(&kobj_sysfs_assoc_lock);

610
	__sysfs_remove_dir(sd);
L
Linus Torvalds 已提交
611 612
}

613
int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
614
		     const char *new_name)
L
Linus Torvalds 已提交
615
{
616 617
	struct sysfs_dirent *sd = kobj->sd;
	struct dentry *new_parent = new_parent_sd->s_dentry;
T
Tejun Heo 已提交
618 619
	struct dentry *new_dentry;
	char *dup_name;
620
	int error;
L
Linus Torvalds 已提交
621

622
	if (!new_parent_sd)
623
		return -EFAULT;
L
Linus Torvalds 已提交
624 625

	down_write(&sysfs_rename_sem);
626
	mutex_lock(&new_parent->d_inode->i_mutex);
L
Linus Torvalds 已提交
627

628
	new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
629 630 631
	if (IS_ERR(new_dentry)) {
		error = PTR_ERR(new_dentry);
		goto out_unlock;
L
Linus Torvalds 已提交
632
	}
633 634 635 636 637 638

	/* By allowing two different directories with the same
	 * d_parent we allow this routine to move between different
	 * shadows of the same directory
	 */
	error = -EINVAL;
639
	if (sd->s_parent->s_dentry->d_inode != new_parent->d_inode ||
640
	    new_dentry->d_parent->d_inode != new_parent->d_inode ||
641
	    new_dentry == sd->s_dentry)
642 643 644 645 646 647
		goto out_dput;

	error = -EEXIST;
	if (new_dentry->d_inode)
		goto out_dput;

T
Tejun Heo 已提交
648 649 650 651 652 653
	/* rename kobject and sysfs_dirent */
	error = -ENOMEM;
	new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
	if (!new_name)
		goto out_drop;

654 655
	error = kobject_set_name(kobj, "%s", new_name);
	if (error)
T
Tejun Heo 已提交
656
		goto out_free;
657

T
Tejun Heo 已提交
658 659 660 661
	kfree(sd->s_name);
	sd->s_name = new_name;

	/* move under the new parent */
662
	d_add(new_dentry, NULL);
663
	d_move(sd->s_dentry, new_dentry);
664

665
	sysfs_unlink_sibling(sd);
666
	sysfs_get(new_parent_sd);
667
	sysfs_put(sd->s_parent);
668
	sd->s_parent = new_parent_sd;
669
	sysfs_link_sibling(sd);
670 671 672 673

	error = 0;
	goto out_unlock;

T
Tejun Heo 已提交
674 675
 out_free:
	kfree(dup_name);
676 677 678 679 680
 out_drop:
	d_drop(new_dentry);
 out_dput:
	dput(new_dentry);
 out_unlock:
681
	mutex_unlock(&new_parent->d_inode->i_mutex);
L
Linus Torvalds 已提交
682 683 684 685
	up_write(&sysfs_rename_sem);
	return error;
}

686 687 688 689 690 691 692
int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
{
	struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
	struct sysfs_dirent *new_parent_sd, *sd;
	int error;

	old_parent_dentry = kobj->parent ?
693
		kobj->parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root;
694
	new_parent_dentry = new_parent ?
695
		new_parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root;
696

M
Mark Lord 已提交
697 698
	if (old_parent_dentry->d_inode == new_parent_dentry->d_inode)
		return 0;	/* nothing to move */
699 700 701 702 703 704 705 706
again:
	mutex_lock(&old_parent_dentry->d_inode->i_mutex);
	if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
		mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
		goto again;
	}

	new_parent_sd = new_parent_dentry->d_fsdata;
707
	sd = kobj->sd;
708 709 710 711 712 713 714 715 716

	new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
				    strlen(kobj->name));
	if (IS_ERR(new_dentry)) {
		error = PTR_ERR(new_dentry);
		goto out;
	} else
		error = 0;
	d_add(new_dentry, NULL);
717
	d_move(sd->s_dentry, new_dentry);
718 719 720
	dput(new_dentry);

	/* Remove from old parent's list and insert into new parent's list. */
721
	sysfs_unlink_sibling(sd);
722 723 724
	sysfs_get(new_parent_sd);
	sysfs_put(sd->s_parent);
	sd->s_parent = new_parent_sd;
725
	sysfs_link_sibling(sd);
726 727 728 729 730 731 732 733

out:
	mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
	mutex_unlock(&old_parent_dentry->d_inode->i_mutex);

	return error;
}

L
Linus Torvalds 已提交
734 735
static int sysfs_dir_open(struct inode *inode, struct file *file)
{
736
	struct dentry * dentry = file->f_path.dentry;
L
Linus Torvalds 已提交
737
	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
738
	struct sysfs_dirent * sd;
L
Linus Torvalds 已提交
739

740
	mutex_lock(&dentry->d_inode->i_mutex);
741
	sd = sysfs_new_dirent("_DIR_", 0, 0);
742 743
	if (sd)
		sysfs_attach_dirent(sd, parent_sd, NULL);
744
	mutex_unlock(&dentry->d_inode->i_mutex);
L
Linus Torvalds 已提交
745

746 747
	file->private_data = sd;
	return sd ? 0 : -ENOMEM;
L
Linus Torvalds 已提交
748 749 750 751
}

static int sysfs_dir_close(struct inode *inode, struct file *file)
{
752
	struct dentry * dentry = file->f_path.dentry;
L
Linus Torvalds 已提交
753 754
	struct sysfs_dirent * cursor = file->private_data;

755
	mutex_lock(&dentry->d_inode->i_mutex);
756
	sysfs_unlink_sibling(cursor);
757
	mutex_unlock(&dentry->d_inode->i_mutex);
L
Linus Torvalds 已提交
758 759 760 761 762 763 764 765 766 767 768 769 770 771

	release_sysfs_dirent(cursor);

	return 0;
}

/* Relationship between s_mode and the DT_xxx types */
static inline unsigned char dt_type(struct sysfs_dirent *sd)
{
	return (sd->s_mode >> 12) & 15;
}

static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
772
	struct dentry *dentry = filp->f_path.dentry;
L
Linus Torvalds 已提交
773 774
	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
	struct sysfs_dirent *cursor = filp->private_data;
775
	struct sysfs_dirent **pos;
L
Linus Torvalds 已提交
776 777 778 779 780
	ino_t ino;
	int i = filp->f_pos;

	switch (i) {
		case 0:
781
			ino = parent_sd->s_ino;
L
Linus Torvalds 已提交
782 783 784 785 786 787
			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
				break;
			filp->f_pos++;
			i++;
			/* fallthrough */
		case 1:
T
Tejun Heo 已提交
788 789 790 791
			if (parent_sd->s_parent)
				ino = parent_sd->s_parent->s_ino;
			else
				ino = parent_sd->s_ino;
L
Linus Torvalds 已提交
792 793 794 795 796 797
			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
				break;
			filp->f_pos++;
			i++;
			/* fallthrough */
		default:
798 799 800 801 802 803 804
			pos = &parent_sd->s_children;
			while (*pos != cursor)
				pos = &(*pos)->s_sibling;

			/* unlink cursor */
			*pos = cursor->s_sibling;

A
Akinobu Mita 已提交
805
			if (filp->f_pos == 2)
806
				pos = &parent_sd->s_children;
A
Akinobu Mita 已提交
807

808 809
			for ( ; *pos; pos = &(*pos)->s_sibling) {
				struct sysfs_dirent *next = *pos;
L
Linus Torvalds 已提交
810 811 812
				const char * name;
				int len;

813
				if (!sysfs_type(next))
L
Linus Torvalds 已提交
814 815
					continue;

T
Tejun Heo 已提交
816
				name = next->s_name;
L
Linus Torvalds 已提交
817
				len = strlen(name);
818
				ino = next->s_ino;
L
Linus Torvalds 已提交
819 820 821

				if (filldir(dirent, name, len, filp->f_pos, ino,
						 dt_type(next)) < 0)
822
					break;
L
Linus Torvalds 已提交
823 824 825

				filp->f_pos++;
			}
826 827 828 829

			/* put cursor back in */
			cursor->s_sibling = *pos;
			*pos = cursor;
L
Linus Torvalds 已提交
830 831 832 833 834 835
	}
	return 0;
}

static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
{
836
	struct dentry * dentry = file->f_path.dentry;
L
Linus Torvalds 已提交
837

838
	mutex_lock(&dentry->d_inode->i_mutex);
L
Linus Torvalds 已提交
839 840 841 842 843 844 845
	switch (origin) {
		case 1:
			offset += file->f_pos;
		case 0:
			if (offset >= 0)
				break;
		default:
846
			mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
L
Linus Torvalds 已提交
847 848 849 850 851 852 853
			return -EINVAL;
	}
	if (offset != file->f_pos) {
		file->f_pos = offset;
		if (file->f_pos >= 2) {
			struct sysfs_dirent *sd = dentry->d_fsdata;
			struct sysfs_dirent *cursor = file->private_data;
854
			struct sysfs_dirent **pos;
L
Linus Torvalds 已提交
855 856
			loff_t n = file->f_pos - 2;

857 858 859 860 861
			sysfs_unlink_sibling(cursor);

			pos = &sd->s_children;
			while (n && *pos) {
				struct sysfs_dirent *next = *pos;
862
				if (sysfs_type(next))
L
Linus Torvalds 已提交
863
					n--;
864
				pos = &(*pos)->s_sibling;
L
Linus Torvalds 已提交
865
			}
866 867 868

			cursor->s_sibling = *pos;
			*pos = cursor;
L
Linus Torvalds 已提交
869 870
		}
	}
871
	mutex_unlock(&dentry->d_inode->i_mutex);
L
Linus Torvalds 已提交
872 873 874
	return offset;
}

875 876 877 878 879 880 881 882 883 884 885 886

/**
 *	sysfs_make_shadowed_dir - Setup so a directory can be shadowed
 *	@kobj:	object we're creating shadow of.
 */

int sysfs_make_shadowed_dir(struct kobject *kobj,
	void * (*follow_link)(struct dentry *, struct nameidata *))
{
	struct inode *inode;
	struct inode_operations *i_op;

887
	inode = kobj->sd->s_dentry->d_inode;
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
	if (inode->i_op != &sysfs_dir_inode_operations)
		return -EINVAL;

	i_op = kmalloc(sizeof(*i_op), GFP_KERNEL);
	if (!i_op)
		return -ENOMEM;

	memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op));
	i_op->follow_link = follow_link;

	/* Locking of inode->i_op?
	 * Since setting i_op is a single word write and they
	 * are atomic we should be ok here.
	 */
	inode->i_op = i_op;
	return 0;
}

/**
 *	sysfs_create_shadow_dir - create a shadow directory for an object.
 *	@kobj:	object we're creating directory for.
 *
 *	sysfs_make_shadowed_dir must already have been called on this
 *	directory.
 */

914
struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj)
915
{
916
	struct dentry *dir = kobj->sd->s_dentry;
T
Tejun Heo 已提交
917 918 919 920
	struct inode *inode = dir->d_inode;
	struct dentry *parent = dir->d_parent;
	struct sysfs_dirent *parent_sd = parent->d_fsdata;
	struct dentry *shadow;
921 922
	struct sysfs_dirent *sd;

923
	sd = ERR_PTR(-EINVAL);
924 925 926 927 928 929 930
	if (!sysfs_is_shadowed_inode(inode))
		goto out;

	shadow = d_alloc(parent, &dir->d_name);
	if (!shadow)
		goto nomem;

931
	sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR);
932 933
	if (!sd)
		goto nomem;
934
	sd->s_elem.dir.kobj = kobj;
T
Tejun Heo 已提交
935 936
	/* point to parent_sd but don't attach to it */
	sd->s_parent = sysfs_get(parent_sd);
937
	sysfs_attach_dirent(sd, NULL, shadow);
938 939 940 941 942 943 944 945

	d_instantiate(shadow, igrab(inode));
	inc_nlink(inode);
	inc_nlink(parent->d_inode);

	dget(shadow);		/* Extra count - pin the dentry in core */

out:
946
	return sd;
947 948
nomem:
	dput(shadow);
949
	sd = ERR_PTR(-ENOMEM);
950 951 952 953 954
	goto out;
}

/**
 *	sysfs_remove_shadow_dir - remove an object's directory.
955
 *	@shadow_sd: sysfs_dirent of shadow directory
956 957 958 959 960 961
 *
 *	The only thing special about this is that we remove any files in
 *	the directory before we remove the directory, and we've inlined
 *	what used to be sysfs_rmdir() below, instead of calling separately.
 */

962
void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd)
963
{
964
	__sysfs_remove_dir(shadow_sd);
965 966
}

967
const struct file_operations sysfs_dir_operations = {
L
Linus Torvalds 已提交
968 969 970 971 972 973
	.open		= sysfs_dir_open,
	.release	= sysfs_dir_close,
	.llseek		= sysfs_dir_lseek,
	.read		= generic_read_dir,
	.readdir	= sysfs_readdir,
};