[PATCH] configfs: Fix failing symlink() making rmdir() fail
authorLouis Rilling <louis.rilling@kerlabs.com>
Fri, 20 Jun 2008 12:09:22 +0000 (14:09 +0200)
committerMark Fasheh <mfasheh@suse.com>
Thu, 31 Jul 2008 23:21:13 +0000 (16:21 -0700)
commit9a73d78cda750f12e25eb811878f2d9dbab1bc6e
treeabdc6537d51ee4faeb41c452428f2bde72abc9c8
parent4768e9b18dc63719209c68920d4ae52dc49b6161
[PATCH] configfs: Fix failing symlink() making rmdir() fail

On a similar pattern as mkdir() vs rmdir(), a failing symlink() may make rmdir()
fail for the symlink's parent and the symlink's target as well.

failing symlink() making target's rmdir() fail:

process 1: process 2:
symlink("A/S" -> "B")
  allow_link()
  create_link()
    attach to "B" links list
rmdir("B")
  detach_prep("B")
    error because of new link
    configfs_create_link("A", "S")
      error (eg -ENOMEM)

failing symlink() making parent's rmdir() fail:

process 1: process 2:
symlink("A/D/S" -> "B")
  allow_link()
  create_link()
    attach to "B" links list
    configfs_create_link("A/D", "S")
      make_dirent("A/D", "S")
rmdir("A")
  detach_prep("A")
    detach_prep("A/D")
      error because of "S"
      create("S")
        error (eg -ENOMEM)

We cannot use the same solution as for mkdir() vs rmdir(), since rmdir() on the
target cannot wait on the i_mutex of the new symlink's parent without risking a
deadlock (with other symlink() or sys_rename()). Instead we define a global
mutex protecting all configfs symlinks attachment, so that rmdir() can avoid the
races above.

Signed-off-by: Louis Rilling <louis.rilling@kerlabs.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
fs/configfs/configfs_internal.h
fs/configfs/dir.c
fs/configfs/symlink.c