Stack Exchange Network

Stack Exchange network consists of 175 Q&A communities including Stack Overflow, the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Visit Stack Exchange
6 added 1189 characters in body
source | link

rmdir doesn't handle link counts

You're confused. rmdir simply doesn't care about link counts. The logic is quite straightforward.

Once a file has a link count of 0, and additionally, no running processes with a reference (file descriptor or current directory), it will be truly deleted. That's the point when the disk space can be re-used for something else [*].

Directories are a file. But unlinking (removing them from their parent) requires more consideration than other types of file. We must make sure each child of the directory is unlinked as well. Otherwise, we could lose the chance to update the children's link count. We would lose that disk space permanently.

So we don't let users call unlink on a directory. Instead, they must use the special-purpose rmdir. Calling rmdir differs from unlink in just two ways

  1. It requires that the directory is "empty", which means that its only children are the standard . and .. entries.
  2. It makes sure to unlink these two remaining entries, before it runs unlink on the directory itself.

That's it. There is no other magic. rmdir is not deferreddeferred until the condition in point 1 holds. rmdir either succeeds or fails at the time it is called. Nor is the condition based on link count in any way.


I find the effect of the . entry on link counts interesting, even though it's not a special case. It's a hard-link to the parent directory, and therefore increases it's link count. This is the explanation for why a newly created directory DIR has a link count of 2. If you then call rmdir DIR, the link count falls back to 0, because it removes both links DIR/. and DIR.


Linux actually allows you to observe the above by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent).

Of course ls -ld is shorthand for ls -ld .. . and .. keep working even after the directory entry is removed; in fact modern Linux does not really rely on these on-disk directory entries. I expect the original Unix implementation would not support this test. However I believe the reference counts still worked as described above, and did not have a special-case for the removal of a directory.

(How .. continues to work is even more interesting. Discussed in comment below).

In fact it would be very easy for you to look at the original Unix code for rmdir. It was implemented as a user program running with special privileges. Historical unix code is easy to find online. It's one reason I'm so confident about this.


[*] So you can see whether a file has been deleted by looking for a difference in used disk blocks in df . (or i-nodes in df -i .). This approach works nicely in filesystems like Linux ext4. Less traditional filesystems may have more complex optimizations though, which can make it harder to observe.


If you want to trace the history here, you might be interested to research how /bin/rmdir used to involve root privileges.

rmdir doesn't handle link counts

You're confused. rmdir simply doesn't care about link counts. The logic is quite straightforward.

Once a file has a link count of 0, and additionally, no running processes with a reference (file descriptor or current directory), it will be truly deleted. That's the point when the disk space can be re-used for something else [*].

Directories are a file. But unlinking (removing them from their parent) requires more consideration than other types of file. We must make sure each child of the directory is unlinked as well. Otherwise, we could lose the chance to update the children's link count. We would lose that disk space permanently.

So we don't let users call unlink on a directory. Instead, they must use the special-purpose rmdir. Calling rmdir differs from unlink in just two ways

  1. It requires that the directory is "empty", which means that its only children are the standard . and .. entries.
  2. It makes sure to unlink these two remaining entries, before it runs unlink on the directory itself.

That's it. There is no other magic. rmdir is not deferred until the condition in point 1 holds. rmdir either succeeds or fails at the time it is called. Nor is the condition based on link count in any way.


I find the effect of the . entry on link counts interesting, even though it's not a special case. It's a hard-link to the parent directory, and therefore increases it's link count. This is the explanation for why a newly created directory DIR has a link count of 2. If you then call rmdir DIR, the link count falls back to 0, because it removes both links DIR/. and DIR.


Linux actually allows you to observe the above by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent).

Of course ls -ld is shorthand for ls -ld .. . and .. keep working even after the directory entry is removed; in fact modern Linux does not really rely on these on-disk directory entries. I expect the original Unix implementation would not support this test. However I believe the reference counts still worked as described above, and did not have a special-case for the removal of a directory.


[*] So you can see whether a file has been deleted by looking for a difference in used disk blocks in df . (or i-nodes in df -i .). This approach works nicely in filesystems like Linux ext4. Less traditional filesystems may have more complex optimizations though, which can make it harder to observe.


If you want to trace the history here, you might be interested to research how /bin/rmdir used to involve root privileges.

You're confused. rmdir simply doesn't care about link counts. The logic is quite straightforward.

Once a file has a link count of 0, and additionally, no running processes with a reference (file descriptor or current directory), it will be truly deleted. That's the point when the disk space can be re-used for something else [*].

Directories are a file. But unlinking (removing them from their parent) requires more consideration than other types of file. We must make sure each child of the directory is unlinked as well. Otherwise, we could lose the chance to update the children's link count. We would lose that disk space permanently.

So we don't let users call unlink on a directory. Instead, they must use the special-purpose rmdir. Calling rmdir differs from unlink in just two ways

  1. It requires that the directory is "empty", which means that its only children are the standard . and .. entries.
  2. It makes sure to unlink these two remaining entries, before it runs unlink on the directory itself.

That's it. There is no other magic. rmdir is not deferred until the condition in point 1 holds. rmdir either succeeds or fails at the time it is called. Nor is the condition based on link count in any way.


I find the effect of the . entry on link counts interesting, even though it's not a special case. It's a hard-link to the parent directory, and therefore increases it's link count. This is the explanation for why a newly created directory DIR has a link count of 2. If you then call rmdir DIR, the link count falls back to 0, because it removes both links DIR/. and DIR.


Linux actually allows you to observe the above by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent).

Of course ls -ld is shorthand for ls -ld .. . and .. keep working even after the directory entry is removed; in fact modern Linux does not really rely on these on-disk directory entries. I expect the original Unix implementation would not support this. However I believe the reference counts still worked as described above, and did not have a special-case for the removal of a directory.

(How .. continues to work is even more interesting. Discussed in comment below).

In fact it would be very easy for you to look at the original Unix code for rmdir. It was implemented as a user program running with special privileges. Historical unix code is easy to find online. It's one reason I'm so confident about this.


[*] So you can see whether a file has been deleted by looking for a difference in used disk blocks in df . (or i-nodes in df -i .). This approach works nicely in filesystems like Linux ext4. Less traditional filesystems may have more complex optimizations though, which can make it harder to observe.

5 added 1189 characters in body
source | link

I think it's quite simple.

rmdir doesn't handle link counts

If You're confused. rmdir TESTD succeeds, then the two links which refer to it, TESTD/. and TESTD are removed. So thesimply doesn't care about link count of the specified directory is reduced by 2counts. This can be verified on Linux by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent) The logic is quite straightforward. [*]

Once a file (such as a directory) has a link count of 0 links, and additionally, no running processes with a reference (file descriptor or current directory), it will be truly deleted. That's the point when the disk space can be re-used for something else [*].

You can tryDirectories are a file. But unlinking (removing them from their parent) requires more consideration than other types of file. We must make sure each child of the directory is unlinked as well. Otherwise, we could lose the chance to observe true deletion by looking atupdate the usedchildren's link count. We would lose that disk blocks inspace permanently.

So we don't let users call df .unlink (or ion a directory. Instead, they must use the special-nodes inpurpose df -i .rmdir). It works in Linux Calling ext4rmdir filesystems. Other filesystems may have more complex optimizations though, making it harder to observe.differs from unlink in just two ways


 
  1. It requires that the directory is "empty", which means that its only children are the standard . and .. entries.
  2. It makes sure to unlink these two remaining entries, before it runs unlink on the directory itself.

That's it. There is no other magic. rmdir fails if "pathname contains entries other than . andis not .deferred until the condition in point 1 holds." (  man 2 rmdir) either succeeds or fails at the time it is called. After Nor is the condition based on link count in any way.


I find the effect of the rmdir. succeedsentry on link counts interesting, even though it's not a special case. It's a hard-link to the parent directory will be completely empty, and therefore increases it's link count. This guarantees that there are no sub-directories, so they won't have anyis the explanation for why a newly created directory DIR has a link count of 2. If you then call ..rmdir DIR links, to keep the directory's link count abovefalls back to 0, because it removes both links DIR/. and DIR.

 

[*]Linux actually allows you to observe the above by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent).

Of course ls -ld is shorthand for ls -ld .. . keepsand .. keep working even after the directory entry is removed; in fact modern Linux does not really rely on these on-disk directory entries. I expect the original Unix implementation would notnot support this test. However I believe the reference counts still worked this wayas described above, and did not have a special-case for the removal of a directory.


[*] So you can see whether a file has been deleted by looking for a difference in used disk blocks in df . (or i-nodes in df -i .). This approach works nicely in filesystems like Linux ext4. Less traditional filesystems may have more complex optimizations though, which can make it harder to observe.


I think it's quite simple.

If rmdir TESTD succeeds, then the two links which refer to it, TESTD/. and TESTD are removed. So the link count of the specified directory is reduced by 2. This can be verified on Linux by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent). [*]

Once a file (such as a directory) has 0 links, and no running processes with a reference (file descriptor or current directory), it will be truly deleted.

You can try to observe true deletion by looking at the used disk blocks in df . (or i-nodes in df -i .). It works in Linux ext4 filesystems. Other filesystems may have more complex optimizations though, making it harder to observe.


 

rmdir fails if "pathname contains entries other than . and .." (man 2 rmdir). After rmdir succeeds, the directory will be completely empty. This guarantees that there are no sub-directories, so they won't have any .. links, to keep the directory's link count above 0.

[*] Of course ls -ld is shorthand for ls -ld .. . keeps working even after the directory entry is removed; in fact modern Linux does not really rely on these on-disk directory entries. I expect the original Unix implementation would not support this test. However I believe the reference counts still worked this way, and did not have a special-case for the removal of a directory.

rmdir doesn't handle link counts

You're confused. rmdir simply doesn't care about link counts. The logic is quite straightforward.

Once a file has a link count of 0, and additionally, no running processes with a reference (file descriptor or current directory), it will be truly deleted. That's the point when the disk space can be re-used for something else [*].

Directories are a file. But unlinking (removing them from their parent) requires more consideration than other types of file. We must make sure each child of the directory is unlinked as well. Otherwise, we could lose the chance to update the children's link count. We would lose that disk space permanently.

So we don't let users call unlink on a directory. Instead, they must use the special-purpose rmdir. Calling rmdir differs from unlink in just two ways

  1. It requires that the directory is "empty", which means that its only children are the standard . and .. entries.
  2. It makes sure to unlink these two remaining entries, before it runs unlink on the directory itself.

That's it. There is no other magic. rmdir is not deferred until the condition in point 1 holds.  rmdir either succeeds or fails at the time it is called. Nor is the condition based on link count in any way.


I find the effect of the . entry on link counts interesting, even though it's not a special case. It's a hard-link to the parent directory, and therefore increases it's link count. This is the explanation for why a newly created directory DIR has a link count of 2. If you then call rmdir DIR, the link count falls back to 0, because it removes both links DIR/. and DIR.

 

Linux actually allows you to observe the above by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent).

Of course ls -ld is shorthand for ls -ld .. . and .. keep working even after the directory entry is removed; in fact modern Linux does not really rely on these on-disk directory entries. I expect the original Unix implementation would not support this test. However I believe the reference counts still worked as described above, and did not have a special-case for the removal of a directory.


[*] So you can see whether a file has been deleted by looking for a difference in used disk blocks in df . (or i-nodes in df -i .). This approach works nicely in filesystems like Linux ext4. Less traditional filesystems may have more complex optimizations though, which can make it harder to observe.


4 added 604 characters in body
source | link

I think it's quite simple.

If rmdir TESTD succeeds, then the two links which refer to it, TESTD/. and TESTD are removed. So the link count of the specified directory is reduced by 2. This can be verified on Linux by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent). [*]

Once a file (such as a directory) has 0 links, and no running processes with a reference (file descriptor or current directory), it will be truly deleted.

You can try to observe true deletion by looking at the used disk blocks in df . (or i-nodes in df -i .). It works in Linux ext4 filesystems. Other filesystems may have more complex optimizations though, making it harder to observe.


rmdir fails if "pathname contains entries other than . and .." (man 2 rmdir). After rmdir succeeds, the directory will be completely empty. This guarantees that there are no sub-directories, so they won't have any .. links, to keep the directory's link count above 0.

[*] Of course ls -ld is shorthand for ls -ld .. . keeps working even after the directory entry is removed; in fact modern Linux does not really rely on these on-disk directory entries. I expect the original Unix implementation would not support this test. However I believe the reference counts still worked this way, and did not have a special-case for the removal of a directory.

If you want to trace the history here, you might be interested to research how /bin/rmdir used to involve root privileges.

I think it's quite simple.

If rmdir TESTD succeeds, then the two links which refer to it, TESTD/. and TESTD are removed. So the link count of the specified directory is reduced by 2. This can be verified by running a shell inside the directory and running ls -ld after the directory has been unlinked (removed from its parent).

Once a file (such as a directory) has 0 links, and no running processes with a reference (file descriptor or current directory), it will be truly deleted.

You can try to observe true deletion by looking at the used disk blocks in df .. It works in Linux ext4 filesystems. Other filesystems may have more complex optimizations though, making it harder to observe.


rmdir fails if "pathname contains entries other than . and .." (man 2 rmdir). After rmdir succeeds, the directory will be completely empty. This guarantees that there are no sub-directories, so they won't have any .. links, to keep the directory's link count above 0.

I think it's quite simple.

If rmdir TESTD succeeds, then the two links which refer to it, TESTD/. and TESTD are removed. So the link count of the specified directory is reduced by 2. This can be verified on Linux by running a shell inside the directory, and running ls -ld after the directory has been unlinked (removed from its parent). [*]

Once a file (such as a directory) has 0 links, and no running processes with a reference (file descriptor or current directory), it will be truly deleted.

You can try to observe true deletion by looking at the used disk blocks in df . (or i-nodes in df -i .). It works in Linux ext4 filesystems. Other filesystems may have more complex optimizations though, making it harder to observe.


rmdir fails if "pathname contains entries other than . and .." (man 2 rmdir). After rmdir succeeds, the directory will be completely empty. This guarantees that there are no sub-directories, so they won't have any .. links, to keep the directory's link count above 0.

[*] Of course ls -ld is shorthand for ls -ld .. . keeps working even after the directory entry is removed; in fact modern Linux does not really rely on these on-disk directory entries. I expect the original Unix implementation would not support this test. However I believe the reference counts still worked this way, and did not have a special-case for the removal of a directory.

If you want to trace the history here, you might be interested to research how /bin/rmdir used to involve root privileges.

3 deleted 47 characters in body
source | link
2 added 124 characters in body
source | link
1
source | link