code:
.. SPDX-License-Identifier: GPL-2.0

===============
Shared Subtrees
===============

.. Contents:
	1) Overview
	2) Features
	3) Setting mount states
	4) Use-case
	5) Detailed semantics
	6) Quiz
	7) FAQ
	8) Implementation

1) Overview
-----------

Consider the following situation:

A process wants to clone its own namespace, but still wants to access the CD
that got mounted recently.  Shared subtree semantics provide the necessary
mechanism to accomplish the above.

It provides the necessary building blocks for features like per-user-namespace
and versioned filesystem.

2) Features
-----------

Shared subtree provides four different flavors of mounts; struct vfsmount to be
precise

	a. shared mount
	b. slave mount
	c. private mount
	d. unbindable mount

2a) A shared mount can be replicated to as many mountpoints and all the
replicas continue to be exactly same.

	Here is an example:

	Let's say /mnt has a mount that is shared::

	    mount --make-shared /mnt

	Note: mount(8) command now supports the --make-shared flag,
	so the sample 'smount' program is no longer needed and has been
	removed.

	::

	    # mount --bind /mnt /tmp

	The above command replicates the mount at /mnt to the mountpoint /tmp
	and the contents of both the mounts remain identical.

	::

	    #ls /mnt
	    a b c

	    #ls /tmp
	    a b c

	Now let's say we mount a device at /tmp/a::

	    # mount /dev/sd0  /tmp/a

	    #ls /tmp/a
	    t1 t2 t3

	    #ls /mnt/a
	    t1 t2 t3

	Note that the mount has propagated to the mount at /mnt as well.

	And the same is true even when /dev/sd0 is mounted on /mnt/a. The
	contents will be visible under /tmp/a too.

2b) A slave mount is like a shared mount except that mount and umount events
	only propagate towards it.

	All slave mounts have a master mount which is a shared.

	Here is an example:

	Let's say /mnt has a mount which is shared.
	# mount --make-shared /mnt

	Let's bind mount /mnt to /tmp
	# mount --bind /mnt /tmp

	the new mount at /tmp becomes a shared mount and it is a replica of
	the mount at /mnt.

	Now let's make the mount at /tmp; a slave of /mnt
	# mount --make-slave /tmp

	let's mount /dev/sd0 on /mnt/a
	# mount /dev/sd0 /mnt/a

	#ls /mnt/a
	t1 t2 t3

	#ls /tmp/a
	t1 t2 t3

	Note the mount event has propagated to the mount at /tmp

	However let's see what happens if we mount something on the mount at /tmp

	# mount /dev/sd1 /tmp/b

	#ls /tmp/b
	s1 s2 s3

	#ls /mnt/b

	Note how the mount event has not propagated to the mount at
	/mnt

2c) A private mount does not forward or receive propagation.

	This is the mount we are familiar with. Its the default type.

2d) A unbindable mount is a unbindable private mount

	let's say we have a mount at /mnt and we make it unbindable::

	    # mount --make-unbindable /mnt

	 Let's try to bind mount this mount somewhere else::

	    # mount --bind /mnt /tmp
	    mount: wrong fs type, bad option, bad superblock on /mnt,
		    or too many mounted file systems

	Binding a unbindable mount is a invalid operation.

3) Setting mount states

	The mount command (util-linux package) can be used to set mount
	states::

	    mount --make-shared mountpoint
	    mount --make-slave mountpoint
	    mount --make-private mountpoint
	    mount --make-unbindable mountpoint

4) Use cases
------------

	A) A process wants to clone its own namespace, but still wants to
	   access the CD that got mounted recently.

	   Solution:

		The system administrator can make the mount at /cdrom shared::

		    mount --bind /cdrom /cdrom
		    mount --make-shared /cdrom

		Now any process that clones off a new namespace will have a
		mount at /cdrom which is a replica of the same mount in the
		parent namespace.

		So when a CD is inserted and mounted at /cdrom that mount gets
		propagated to the other mount at /cdrom in all the other clone
		namespaces.

	B) A process wants its mounts invisible to any other process, but
	still be able to see the other system mounts.

	   Solution:

		To begin with, the administrator can mark the entire mount tree
		as shareable::

		    mount --make-rshared /

		A new process can clone off a new namespace. And mark some part
		of its namespace as slave::

		    mount --make-rslave /myprivatetree

		Hence forth any mounts within the /myprivatetree done by the
		process will not show up in any other namespace. However mounts
		done in the parent namespace under /myprivatetree still shows
		up in the process's namespace.

	Apart from the above semantics this feature provides the
	building blocks to solve the following problems:

	C)  Per-user namespace

		The above semantics allows a way to share mounts across
		namespaces.  But namespaces are associated with processes. If
		namespaces are made first class objects with user API to
		associate/disassociate a namespace with userid, then each user
		could have his/her own namespace and tailor it to his/her
		requirements. This needs to be supported in PAM.

	D)  Versioned files

		If the entire mount tree is visible at multiple locations, then
		an underlying versioning file system can return different
		versions of the file depending on the path used to access that
		file.

		An example is::

		    mount --make-shared /
		    mount --rbind / /view/v1
		    mount --rbind / /view/v2
		    mount --rbind / /view/v3
		    mount --rbind / /view/v4

		and if /usr has a versioning filesystem mounted, then that
		mount appears at /view/v1/usr, /view/v2/usr, /view/v3/usr and
		/view/v4/usr too

		A user can request v3 version of the file /usr/fs/namespace.c
		by accessing /view/v3/usr/fs/namespace.c . The underlying
		versioning filesystem can then decipher that v3 version of the
		filesystem is being requested and return the corresponding
		inode.

5) Detailed semantics
---------------------
	The section below explains the detailed semantics of
	bind, rbind, move, mount, umount and clone-namespace operations.

	Note: the word 'vfsmount' and the noun 'mount' have been used
	to mean the same thing, throughout this document.

5a) Mount states

	A given mount can be in one of the following states

	1) shared
	2) slave
	3) shared and slave
	4) private
	5) unbindable

	A 'propagation event' is defined as event generated on a vfsmount
	that leads to mount or unmount actions in other vfsmounts.

	A 'peer group' is defined as a group of vfsmounts that propagate
	events to each other.

	(1) Shared mounts

		A 'shared mount' is defined as a vfsmount that belongs to a
		'peer group'.

		For example::

			mount --make-shared /mnt
			mount --bind /mnt /tmp

		The mount at /mnt and that at /tmp are both shared and belong
		to the same peer group. Anything mounted or unmounted under
		/mnt or /tmp reflect in all the other mounts of its peer
		group.

	(2) Slave mounts

		A 'slave mount' is defined as a vfsmount that receives
		propagation events and does not forward propagation events.

		A slave mount as the name implies has a master mount from which
		mount/unmount events are received. Events do not propagate from
		the slave mount to the master.  Only a shared mount can be made
		a slave by executing the following command::

			mount --make-slave mount

		A shared mount that is made as a slave is no more shared unless
		modified to become shared.

	(3) Shared and Slave

		A vfsmount can be both shared as well as slave.  This state
		indicates that the mount is a slave of some vfsmount, and
		has its own peer group too.  This vfsmount receives propagation
		events from its master vfsmount, and also forwards propagation
		events to its 'peer group' and to its slave vfsmounts.

		Strictly speaking, the vfsmount is shared having its own
		peer group, and this peer-group is a slave of some other
		peer group.

		Only a slave vfsmount can be made as 'shared and slave' by
		either executing the following command::

			mount --make-shared mount

		or by moving the slave vfsmount under a shared vfsmount.

	(4) Private mount

		A 'private mount' is defined as vfsmount that does not
		receive or forward any propagation events.

	(5) Unbindable mount

		A 'unbindable mount' is defined as vfsmount that does not
		receive or forward any propagation events and cannot
		be bind mounted.

   	State diagram:

   	The state diagram below explains the state transition of a mount,
	in response to various commands::

	    -----------------------------------------------------------------------
	    |             |make-shared |  make-slave  | make-private |make-unbindab|
	    --------------|------------|--------------|--------------|-------------|
	    |shared	  |shared      |*slave/private|   private    | unbindable  |
	    |             |            |              |              |             |
	    |-------------|------------|--------------|--------------|-------------|
	    |slave	  |shared      | **slave      |    private   | unbindable  |
	    |             |and slave   |              |              |             |
	    |-------------|------------|--------------|--------------|-------------|
	    |shared       |shared      | slave        |    private   | unbindable  |
	    |and slave    |and slave   |              |              |             |
	    |-------------|------------|--------------|--------------|-------------|
	    |private      |shared      |  **private   |    private   | unbindable  |
	    |-------------|------------|--------------|--------------|-------------|
	    |unbindable   |shared      |**unbindable  |    private   | unbindable  |
	    ------------------------------------------------------------------------

	    * if the shared mount is the only mount in its peer group, making it
	    slave, makes it private automatically. Note that there is no master to
	    which it can be slaved to.

	    ** slaving a non-shared mount has no effect on the mount.

	Apart from the commands listed below, the 'move' operation also changes
	the state of a mount depending on type of the destination mount. Its
	explained in section 5d.

5b) Bind semantics

	Consider the following command::

	    mount --bind A/a  B/b

	where 'A' is the source mount, 'a' is the dentry in the mount 'A', 'B'
	is the destination mount and 'b' is the dentry in the destination mount.

	The outcome depends on the type of mount of 'A' and 'B'. The table
	below contains quick reference::

	    --------------------------------------------------------------------------
	    |         BIND MOUNT OPERATION                                           |
	    |************************************************************************|
	    |source(A)->| shared      |       private  |       slave    | unbindable |
	    | dest(B)  |              |                |                |            |
	    |   |      |              |                |                |            |
	    |   v      |              |                |                |            |
	    |************************************************************************|
	    |  shared  | shared       |     shared     | shared & slave |  invalid   |
	    |          |              |                |                |            |
	    |non-shared| shared       |      private   |      slave     |  invalid   |
	    **************************************************************************

     	Details:

    1. 'A' is a shared mount and 'B' is a shared mount. A new mount 'C'
	which is clone of 'A', is created. Its root dentry is 'a' . 'C' is
	mounted on mount 'B' at dentry 'b'. Also new mount 'C1', 'C2', 'C3' ...
	are created and mounted at the dentry 'b' on all mounts where 'B'
	propagates to. A new propagation tree containing 'C1',..,'Cn' is
	created. This propagation tree is identical to the propagation tree of
	'B'.  And finally the peer-group of 'C' is merged with the peer group
	of 'A'.

    2. 'A' is a private mount and 'B' is a shared mount. A new mount 'C'
	which is clone of 'A', is created. Its root dentry is 'a'. 'C' is
	mounted on mount 'B' at dentry 'b'. Also new mount 'C1', 'C2', 'C3' ...
	are created and mounted at the dentry 'b' on all mounts where 'B'
	propagates to. A new propagation tree is set containing all new mounts
	'C', 'C1', .., 'Cn' with exactly the same configuration as the
	propagation tree for 'B'.

    3. 'A' is a slave mount of mount 'Z' and 'B' is a shared mount. A new
	mount 'C' which is clone of 'A', is created. Its root dentry is 'a' .
	'C' is mounted on mount 'B' at dentry 'b'. Also new mounts 'C1', 'C2',
	'C3' ... are created and mounted at the dentry 'b' on all mounts where
	'B' propagates to. A new propagation tree containing the new mounts
	'C','C1',..  'Cn' is created. This propagation tree is identical to the
	propagation tree for 'B'. And finally the mount 'C' and its peer group
	is made the slave of mount 'Z'.  In other words, mount 'C' is in the
	state 'slave and shared'.

    4. 'A' is a unbindable mount and 'B' is a shared mount. This is a
	invalid operation.

    5. 'A' is a private mount and 'B' is a non-shared(private or slave or
	unbindable) mount. A new mount 'C' which is clone of 'A', is created.
	Its root dentry is 'a'. 'C' is mounted on mount 'B' at dentry 'b'.

    6. 'A' is a shared mount and 'B' is a non-shared mount. A new mount 'C'
	which is a clone of 'A' is created. Its root dentry is 'a'. 'C' is
	mounted on mount 'B' at dentry 'b'.  'C' is made a member of the
	peer-group of 'A'.

    7. 'A' is a slave mount of mount 'Z' and 'B' is a non-shared mount. A
	new mount 'C' which is a clone of 'A' is created. Its root dentry is
	'a'.  'C' is mounted on mount 'B' at dentry 'b'. Also 'C' is set as a
	slave mount of 'Z'. In other words 'A' and 'C' are both slave mounts of
	'Z'.  All mount/unmount events on 'Z' propagates to 'A' and 'C'. But
	mount/unmount on 'A' do not propagate anywhere else. Similarly
	mount/unmount on 'C' do not propagate anywhere else.

    8. 'A' is a unbindable mount and 'B' is a non-shared mount. This is a
	invalid operation. A unbindable mount cannot be bind mounted.

5c) Rbind semantics

	rbind is same as bind. Bind replicates the specified mount.  Rbind
	replicates all the mounts in the tree belonging to the specified mount.
	Rbind mount is bind mount applied to all the mounts in the tree.

	If the source tree that is rbind has some unbindable mounts,
	then the subtree under the unbindable mount is pruned in the new
	location.

	eg:

	  let's say we have the following mount tree::

		A
	      /   \
	      B   C
	     / \ / \
	     D E F G

	  Let's say all the mount except the mount C in the tree are
	  of a type other than unbindable.

	  If this tree is rbound to say Z

	  We will have the following tree at the new location::

		Z
		|
		A'
	       /
	      B'		Note how the tree under C is pruned
	     / \ 		in the new location.
	    D' E'

5d) Move semantics

	Consider the following command

	mount --move A  B/b

	where 'A' is the source mount, 'B' is the destination mount and 'b' is
	the dentry in the destination mount.

	The outcome depends on the type of the mount of 'A' and 'B'. The table
	below is a quick reference::

	    ---------------------------------------------------------------------------
	    |         		MOVE MOUNT OPERATION                                 |
	    |**************************************************************************
	    | source(A)->| shared      |       private  |       slave    | unbindable |
	    | dest(B)  |               |                |                |            |
	    |   |      |               |                |                |            |
	    |   v      |               |                |                |            |
	    |**************************************************************************
	    |  shared  | shared        |     shared     |shared and slave|  invalid   |
	    |          |               |                |                |            |
	    |non-shared| shared        |      private   |    slave       | unbindable |
	    ***************************************************************************

	.. Note:: moving a mount residing under a shared mount is invalid.

      Details follow:

    1. 'A' is a shared mount and 'B' is a shared mount.  The mount 'A' is
	mounted on mount 'B' at dentry 'b'.  Also new mounts 'A1', 'A2'...'An'
	are created and mounted at dentry 'b' on all mounts that receive
	propagation from mount 'B'. A new propagation tree is created in the
	exact same configuration as that of 'B'. This new propagation tree
	contains all the new mounts 'A1', 'A2'...  'An'.  And this new
	propagation tree is appended to the already existing propagation tree
	of 'A'.

    2. 'A' is a private mount and 'B' is a shared mount. The mount 'A' is
	mounted on mount 'B' at dentry 'b'. Also new mount 'A1', 'A2'... 'An'
	are created and mounted at dentry 'b' on all mounts that receive
	propagation from mount 'B'. The mount 'A' becomes a shared mount and a
	propagation tree is created which is identical to that of
	'B'. This new propagation tree contains all the new mounts 'A1',
	'A2'...  'An'.

    3. 'A' is a slave mount of mount 'Z' and 'B' is a shared mount.  The
	mount 'A' is mounted on mount 'B' at dentry 'b'.  Also new mounts 'A1',
	'A2'... 'An' are created and mounted at dentry 'b' on all mounts that
	receive propagation from mount 'B'. A new propagation tree is created
	in the exact same configuration as that of 'B'. This new propagation
	tree contains all the new mounts 'A1', 'A2'...  'An'.  And this new
	propagation tree is appended to the already existing propagation tree of
	'A'.  Mount 'A' continues to be the slave mount of 'Z' but it also
	becomes 'shared'.

    4. 'A' is a unbindable mount and 'B' is a shared mount. The operation
	is invalid. Because mounting anything on the shared mount 'B' can
	create new mounts that get mounted on the mounts that receive
	propagation from 'B'.  And since the mount 'A' is unbindable, cloning
	it to mount at other mountpoints is not possible.

    5. 'A' is a private mount and 'B' is a non-shared(private or slave or
	unbindable) mount. The mount 'A' is mounted on mount 'B' at dentry 'b'.

    6. 'A' is a shared mount and 'B' is a non-shared mount.  The mount 'A'
	is mounted on mount 'B' at dentry 'b'.  Mount 'A' continues to be a
	shared mount.

    7. 'A' is a slave mount of mount 'Z' and 'B' is a non-shared mount.
	The mount 'A' is mounted on mount 'B' at dentry 'b'.  Mount 'A'
	continues to be a slave mount of mount 'Z'.

    8. 'A' is a unbindable mount and 'B' is a non-shared mount. The mount
	'A' is mounted on mount 'B' at dentry 'b'. Mount 'A' continues to be a
	unbindable mount.

5e) Mount semantics

	Consider the following command::

	    mount device  B/b

	'B' is the destination mount and 'b' is the dentry in the destination
	mount.

	The above operation is the same as bind operation with the exception
	that the source mount is always a private mount.

5f) Unmount semantics

	Consider the following command::

	    umount A

	where 'A' is a mount mounted on mount 'B' at dentry 'b'.

	If mount 'B' is shared, then all most-recently-mounted mounts at dentry
	'b' on mounts that receive propagation from mount 'B' and does not have
	sub-mounts within them are unmounted.

	Example: Let's say 'B1', 'B2', 'B3' are shared mounts that propagate to
	each other.

	let's say 'A1', 'A2', 'A3' are first mounted at dentry 'b' on mount
	'B1', 'B2' and 'B3' respectively.

	let's say 'C1', 'C2', 'C3' are next mounted at the same dentry 'b' on
	mount 'B1', 'B2' and 'B3' respectively.

	if 'C1' is unmounted, all the mounts that are most-recently-mounted on
	'B1' and on the mounts that 'B1' propagates-to are unmounted.

	'B1' propagates to 'B2' and 'B3'. And the most recently mounted mount
	on 'B2' at dentry 'b' is 'C2', and that of mount 'B3' is 'C3'.

	So all 'C1', 'C2' and 'C3' should be unmounted.

	If any of 'C2' or 'C3' has some child mounts, then that mount is not
	unmounted, but all other mounts are unmounted. However if 'C1' is told
	to be unmounted and 'C1' has some sub-mounts, the umount operation is
	failed entirely.

5g) Clone Namespace

	A cloned namespace contains all the mounts as that of the parent
	namespace.

	Let's say 'A' and 'B' are the corresponding mounts in the parent and the
	child namespace.

	If 'A' is shared, then 'B' is also shared and 'A' and 'B' propagate to
	each other.

	If 'A' is a slave mount of 'Z', then 'B' is also the slave mount of
	'Z'.

	If 'A' is a private mount, then 'B' is a private mount too.

	If 'A' is unbindable mount, then 'B' is a unbindable mount too.

6) Quiz

	A. What is the result of the following command sequence?

		::

		    mount --bind /mnt /mnt
		    mount --make-shared /mnt
		    mount --bind /mnt /tmp
		    mount --move /tmp /mnt/1

		what should be the contents of /mnt /mnt/1 /mnt/1/1 should be?
		Should they all be identical? or should /mnt and /mnt/1 be
		identical only?

	B. What is the result of the following command sequence?

		::

		    mount --make-rshared /
		    mkdir -p /v/1
		    mount --rbind / /v/1

		what should be the content of /v/1/v/1 be?

	C. What is the result of the following command sequence?

		::

		    mount --bind /mnt /mnt
		    mount --make-shared /mnt
		    mkdir -p /mnt/1/2/3 /mnt/1/test
		    mount --bind /mnt/1 /tmp
		    mount --make-slave /mnt
		    mount --make-shared /mnt
		    mount --bind /mnt/1/2 /tmp1
		    mount --make-slave /mnt

		At this point we have the first mount at /tmp and
		its root dentry is 1. Let's call this mount 'A'
		And then we have a second mount at /tmp1 with root
		dentry 2. Let's call this mount 'B'
		Next we have a third mount at /mnt with root dentry
		mnt. Let's call this mount 'C'

		'B' is the slave of 'A' and 'C' is a slave of 'B'
		A -> B -> C

		at this point if we execute the following command

		mount --bind /bin /tmp/test

		The mount is attempted on 'A'

		will the mount propagate to 'B' and 'C' ?

		what would be the contents of
		/mnt/1/test be?

7) FAQ

	Q1. Why is bind mount needed? How is it different from symbolic links?
		symbolic links can get stale if the destination mount gets
		unmounted or moved. Bind mounts continue to exist even if the
		other mount is unmounted or moved.

	Q2. Why can't the shared subtree be implemented using exportfs?

		exportfs is a heavyweight way of accomplishing part of what
		shared subtree can do. I cannot imagine a way to implement the
		semantics of slave mount using exportfs?

	Q3 Why is unbindable mount needed?

		Let's say we want to replicate the mount tree at multiple
		locations within the same subtree.

		if one rbind mounts a tree within the same subtree 'n' times
		the number of mounts created is an exponential function of 'n'.
		Having unbindable mount can help prune the unneeded bind
		mounts. Here is an example.

		step 1:
		   let's say the root tree has just two directories with
		   one vfsmount::

				    root
				   /    \
				  tmp    usr

		    And we want to replicate the tree at multiple
		    mountpoints under /root/tmp

		step 2:
		      ::

			mount --make-shared /root

			mkdir -p /tmp/m1

			mount --rbind /root /tmp/m1

		      the new tree now looks like this::

				    root
				   /    \
				 tmp    usr
				/
			       m1
			      /  \
			     tmp  usr
			     /
			    m1

			  it has two vfsmounts

		step 3:
		    ::

			    mkdir -p /tmp/m2
			    mount --rbind /root /tmp/m2

			the new tree now looks like this::

				      root
				     /    \
				   tmp     usr
				  /    \
				m1       m2
			       / \       /  \
			     tmp  usr   tmp  usr
			     / \          /
			    m1  m2      m1
				/ \     /  \
			      tmp usr  tmp   usr
			      /        / \
			     m1       m1  m2
			    /  \
			  tmp   usr
			  /  \
			 m1   m2

		       it has 6 vfsmounts

		step 4:
		      ::
			  mkdir -p /tmp/m3
			  mount --rbind /root /tmp/m3

			  I won't draw the tree..but it has 24 vfsmounts

		at step i the number of vfsmounts is V[i] = i*V[i-1].
		This is an exponential function. And this tree has way more
		mounts than what we really needed in the first place.

		One could use a series of umount at each step to prune
		out the unneeded mounts. But there is a better solution.
		Unclonable mounts come in handy here.

		step 1:
		   let's say the root tree has just two directories with
		   one vfsmount::

				    root
				   /    \
				  tmp    usr

		    How do we set up the same tree at multiple locations under
		    /root/tmp

		step 2:
		      ::

			mount --bind /root/tmp /root/tmp

			mount --make-rshared /root
			mount --make-unbindable /root/tmp

			mkdir -p /tmp/m1

			mount --rbind /root /tmp/m1

		      the new tree now looks like this::

				    root
				   /    \
				 tmp    usr
				/
			       m1
			      /  \
			     tmp  usr

		step 3:
		      ::

			    mkdir -p /tmp/m2
			    mount --rbind /root /tmp/m2

		      the new tree now looks like this::

				    root
				   /    \
				 tmp    usr
				/   \
			       m1     m2
			      /  \     / \
			     tmp  usr tmp usr

		step 4:
		      ::

			    mkdir -p /tmp/m3
			    mount --rbind /root /tmp/m3

		      the new tree now looks like this::

				    	  root
				      /    	  \
				     tmp    	   usr
			         /    \    \
			       m1     m2     m3
			      /  \     / \    /  \
			     tmp  usr tmp usr tmp usr

8) Implementation

8A) Datastructure

	4 new fields are introduced to struct vfsmount:

	*   ->mnt_share
	*   ->mnt_slave_list
	*   ->mnt_slave
	*   ->mnt_master

	->mnt_share
		links together all the mount to/from which this vfsmount
		send/receives propagation events.

	->mnt_slave_list
		links all the mounts to which this vfsmount propagates
		to.

	->mnt_slave
		links together all the slaves that its master vfsmount
		propagates to.

	->mnt_master
		points to the master vfsmount from which this vfsmount
		receives propagation.

	->mnt_flags
		takes two more flags to indicate the propagation status of
		the vfsmount.  MNT_SHARE indicates that the vfsmount is a shared
		vfsmount.  MNT_UNCLONABLE indicates that the vfsmount cannot be
		replicated.

	All the shared vfsmounts in a peer group form a cyclic list through
	->mnt_share.

	All vfsmounts with the same ->mnt_master form on a cyclic list anchored
	in ->mnt_master->mnt_slave_list and going through ->mnt_slave.

	 ->mnt_master can point to arbitrary (and possibly different) members
	 of master peer group.  To find all immediate slaves of a peer group
	 you need to go through _all_ ->mnt_slave_list of its members.
	 Conceptually it's just a single set - distribution among the
	 individual lists does not affect propagation or the way propagation
	 tree is modified by operations.

	All vfsmounts in a peer group have the same ->mnt_master.  If it is
	non-NULL, they form a contiguous (ordered) segment of slave list.

	A example propagation tree looks as shown in the figure below.
	[ NOTE: Though it looks like a forest, if we consider all the shared
	mounts as a conceptual entity called 'pnode', it becomes a tree]::

		        A <--> B <--> C <---> D
		       /|\	      /|      |\
		      / F G	     J K      H I
		     /
		    E<-->K
			/|\
		       M L N

	In the above figure  A,B,C and D all are shared and propagate to each
	other.   'A' has got 3 slave mounts 'E' 'F' and 'G' 'C' has got 2 slave
	mounts 'J' and 'K'  and  'D' has got two slave mounts 'H' and 'I'.
	'E' is also shared with 'K' and they propagate to each other.  And
	'K' has 3 slaves 'M', 'L' and 'N'

	A's ->mnt_share links with the ->mnt_share of 'B' 'C' and 'D'

	A's ->mnt_slave_list links with ->mnt_slave of 'E', 'K', 'F' and 'G'

	E's ->mnt_share links with ->mnt_share of K

	'E', 'K', 'F', 'G' have their ->mnt_master point to struct vfsmount of 'A'

	'M', 'L', 'N' have their ->mnt_master point to struct vfsmount of 'K'

	K's ->mnt_slave_list links with ->mnt_slave of 'M', 'L' and 'N'

	C's ->mnt_slave_list links with ->mnt_slave of 'J' and 'K'

	J and K's ->mnt_master points to struct vfsmount of C

	and finally D's ->mnt_slave_list links with ->mnt_slave of 'H' and 'I'

	'H' and 'I' have their ->mnt_master pointing to struct vfsmount of 'D'.

	NOTE: The propagation tree is orthogonal to the mount tree.

8B Locking:

	->mnt_share, ->mnt_slave, ->mnt_slave_list, ->mnt_master are protected
	by namespace_sem (exclusive for modifications, shared for reading).

	Normally we have ->mnt_flags modifications serialized by vfsmount_lock.
	There are two exceptions: do_add_mount() and clone_mnt().
	The former modifies a vfsmount that has not been visible in any shared
	data structures yet.
	The latter holds namespace_sem and the only references to vfsmount
	are in lists that can't be traversed without namespace_sem.

8C Algorithm:

	The crux of the implementation resides in rbind/move operation.

	The overall algorithm breaks the operation into 3 phases: (look at
	attach_recursive_mnt() and propagate_mnt())

	1. prepare phase.
	2. commit phases.
	3. abort phases.

	Prepare phase:

	for each mount in the source tree:

		   a) Create the necessary number of mount trees to
		   	be attached to each of the mounts that receive
			propagation from the destination mount.
		   b) Do not attach any of the trees to its destination.
		      However note down its ->mnt_parent and ->mnt_mountpoint
		   c) Link all the new mounts to form a propagation tree that
		      is identical to the propagation tree of the destination
		      mount.

		   If this phase is successful, there should be 'n' new
		   propagation trees; where 'n' is the number of mounts in the
		   source tree.  Go to the commit phase

		   Also there should be 'm' new mount trees, where 'm' is
		   the number of mounts to which the destination mount
		   propagates to.

		   if any memory allocations fail, go to the abort phase.

	Commit phase
		attach each of the mount trees to their corresponding
		destination mounts.

	Abort phase
		delete all the newly created trees.

	.. Note::
	   all the propagation related functionality resides in the file pnode.c

------------------------------------------------------------------------

version 0.1  (created the initial document, Ram Pai linuxram@us.ibm.com)

version 0.2  (Incorporated comments from Al Viro)


code:
================
splice and pipes
================

splice API
==========

splice is a method for moving blocks of data around inside the kernel,
without continually transferring them between the kernel and user space.

.. kernel-doc:: fs/splice.c

pipes API
=========

Pipe interfaces are all for in-kernel (builtin image) use. They are not
exported for use by modules.

.. kernel-doc:: include/linux/pipe_fs_i.h
   :internal:

.. kernel-doc:: fs/pipe.c

repo_name: angery/linux


code:
.. SPDX-License-Identifier: GPL-2.0

==============
SPU Filesystem
==============

.. toctree::
   :maxdepth: 1

   spufs
   spu_create
   spu_run


code:
.. SPDX-License-Identifier: GPL-2.0

==========
spu_create
==========

Name
====
       spu_create - create a new spu context

Synopsis
========

       ::

         #include <sys/types.h>
         #include <sys/spu.h>

         int spu_create(const char *pathname, int flags, mode_t mode);

Description
===========
       The  spu_create  system call is used on PowerPC machines that implement
       the Cell Broadband Engine Architecture in order to  access  Synergistic
       Processor  Units (SPUs). It creates a new logical context for an SPU in
       pathname and returns a handle to associated  with  it.   pathname  must
       point  to  a  non-existing directory in the mount point of the SPU file
       system (spufs).  When spu_create is successful, a directory  gets  cre-
       ated on pathname and it is populated with files.

       The  returned  file  handle can only be passed to spu_run(2) or closed,
       other operations are not defined on it. When it is closed, all  associ-
       ated  directory entries in spufs are removed. When the last file handle
       pointing either inside  of  the  context  directory  or  to  this  file
       descriptor is closed, the logical SPU context is destroyed.

       The  parameter flags can be zero or any bitwise or'd combination of the
       following constants:

       SPU_RAWIO
              Allow mapping of some of the hardware registers of the SPU  into
              user space. This flag requires the CAP_SYS_RAWIO capability, see
              capabilities(7).

       The mode parameter specifies the permissions used for creating the  new
       directory  in  spufs.   mode is modified with the user's umask(2) value
       and then used for both the directory and the files contained in it. The
       file permissions mask out some more bits of mode because they typically
       support only read or write access. See stat(2) for a full list  of  the
       possible mode values.

Return Value
============
       spu_create  returns a new file descriptor. It may return -1 to indicate
       an error condition and set errno to  one  of  the  error  codes  listed
       below.

Errors
======
       EACCES
              The  current  user does not have write access on the spufs mount
              point.

       EEXIST An SPU context already exists at the given path name.

       EFAULT pathname is not a valid string pointer in  the  current  address
              space.

       EINVAL pathname is not a directory in the spufs mount point.

       ELOOP  Too many symlinks were found while resolving pathname.

       EMFILE The process has reached its maximum open file limit.

       ENAMETOOLONG
              pathname was too long.

       ENFILE The system has reached the global open file limit.

       ENOENT Part of pathname could not be resolved.

       ENOMEM The kernel could not allocate all resources required.

       ENOSPC There  are  not  enough  SPU resources available to create a new
              context or the user specific limit for the number  of  SPU  con-
              texts has been reached.

       ENOSYS the functionality is not provided by the current system, because
              either the hardware does not provide SPUs or the spufs module is
              not loaded.

       ENOTDIR
              A part of pathname is not a directory.

Notes
=====
       spu_create  is  meant  to  be used from libraries that implement a more
       abstract interface to SPUs, not to be used from  regular  applications.
       See  http://www.bsc.es/projects/deepcomputing/linuxoncell/ for the rec-
       ommended libraries.

Files
=====
       pathname must point to a location beneath the mount point of spufs.  By
       convention, it gets mounted in /spu.

Conforming to
=============
       This call is Linux specific and only implemented by the ppc64 architec-
       ture. Programs using this system call are not portable.

Bugs
====
       The code does not yet fully implement all features lined out here.

Author
======
       Arnd Bergmann <arndb@de.ibm.com>

See Also
========
       capabilities(7), close(2), spu_run(2), spufs(7)


code:
.. SPDX-License-Identifier: GPL-2.0

=======
spu_run
=======

Name
====
       spu_run - execute an spu context

Synopsis
========

       ::

	    #include <sys/spu.h>

	    int spu_run(int fd, unsigned int *npc, unsigned int *event);

Description
===========
       The  spu_run system call is used on PowerPC machines that implement the
       Cell Broadband Engine Architecture in order to access Synergistic  Pro-
       cessor  Units  (SPUs).  It  uses the fd that was returned from spu_cre-
       ate(2) to address a specific SPU context. When the context gets  sched-
       uled  to a physical SPU, it starts execution at the instruction pointer
       passed in npc.

       Execution of SPU code happens synchronously, meaning that spu_run  does
       not  return  while the SPU is still running. If there is a need to exe-
       cute SPU code in parallel with other code on either  the  main  CPU  or
       other  SPUs,  you  need to create a new thread of execution first, e.g.
       using the pthread_create(3) call.

       When spu_run returns, the current value of the SPU instruction  pointer
       is  written back to npc, so you can call spu_run again without updating
       the pointers.

       event can be a NULL pointer or point to an extended  status  code  that
       gets  filled  when spu_run returns. It can be one of the following con-
       stants:

       SPE_EVENT_DMA_ALIGNMENT
              A DMA alignment error

       SPE_EVENT_SPE_DATA_SEGMENT
              A DMA segmentation error

       SPE_EVENT_SPE_DATA_STORAGE
              A DMA storage error

       If NULL is passed as the event argument, these errors will result in  a
       signal delivered to the calling process.

Return Value
============
       spu_run  returns the value of the spu_status register or -1 to indicate
       an error and set errno to one of the error  codes  listed  below.   The
       spu_status  register  value  contains  a  bit  mask of status codes and
       optionally a 14 bit code returned from the stop-and-signal  instruction
       on the SPU. The bit masks for the status codes are:

       0x02
	      SPU was stopped by stop-and-signal.

       0x04
	      SPU was stopped by halt.

       0x08
	      SPU is waiting for a channel.

       0x10
	      SPU is in single-step mode.

       0x20
	      SPU has tried to execute an invalid instruction.

       0x40
	      SPU has tried to access an invalid channel.

       0x3fff0000
              The  bits  masked with this value contain the code returned from
              stop-and-signal.

       There are always one or more of the lower eight bits set  or  an  error
       code is returned from spu_run.

Errors
======
       EAGAIN or EWOULDBLOCK
              fd is in non-blocking mode and spu_run would block.

       EBADF  fd is not a valid file descriptor.

       EFAULT npc is not a valid pointer or status is neither NULL nor a valid
              pointer.

       EINTR  A signal occurred while spu_run was in progress.  The npc  value
              has  been updated to the new program counter value if necessary.

       EINVAL fd is not a file descriptor returned from spu_create(2).

       ENOMEM Insufficient memory was available to handle a page fault result-
              ing from an MFC direct memory access.

       ENOSYS the functionality is not provided by the current system, because
              either the hardware does not provide SPUs or the spufs module is
              not loaded.

Notes
=====
       spu_run  is  meant  to  be  used  from  libraries that implement a more
       abstract interface to SPUs, not to be used from  regular  applications.
       See  http://www.bsc.es/projects/deepcomputing/linuxoncell/ for the rec-
       ommended libraries.

Conforming to
=============
       This call is Linux specific and only implemented by the ppc64 architec-
       ture. Programs using this system call are not portable.

Bugs
====
       The code does not yet fully implement all features lined out here.

Author
======
       Arnd Bergmann <arndb@de.ibm.com>

See Also
========
       capabilities(7), close(2), spu_create(2), spufs(7)


code:
.. SPDX-License-Identifier: GPL-2.0

=====
spufs
=====

Name
====

       spufs - the SPU file system

Description
===========

       The SPU file system is used on PowerPC machines that implement the Cell
       Broadband Engine Architecture in order to access Synergistic  Processor
       Units (SPUs).

       The file system provides a name space similar to posix shared memory or
       message queues. Users that have write permissions on  the  file  system
       can use spu_create(2) to establish SPU contexts in the spufs root.

       Every SPU context is represented by a directory containing a predefined
       set of files. These files can be used for manipulating the state of the
       logical SPU. Users can change permissions on those files, but not actu-
       ally add or remove files.

Mount Options
=============

       uid=<uid>
              set the user owning the mount point, the default is 0 (root).

       gid=<gid>
              set the group owning the mount point, the default is 0 (root).

Files
=====

       The files in spufs mostly follow the standard behavior for regular sys-
       tem  calls like read(2) or write(2), but often support only a subset of
       the operations supported on regular file systems. This list details the
       supported  operations  and  the  deviations  from  the behaviour in the
       respective man pages.

       All files that support the read(2) operation also support readv(2)  and
       all  files  that support the write(2) operation also support writev(2).
       All files support the access(2) and stat(2) family of  operations,  but
       only  the  st_mode,  st_nlink,  st_uid and st_gid fields of struct stat
       contain reliable information.

       All files support the chmod(2)/fchmod(2) and chown(2)/fchown(2)  opera-
       tions,  but  will  not be able to grant permissions that contradict the
       possible operations, e.g. read access on the wbox file.

       The current set of files is:

   /mem
       the contents of the local storage memory  of  the  SPU.   This  can  be
       accessed  like  a regular shared memory file and contains both code and
       data in the address space of the SPU.  The possible  operations  on  an
       open mem file are:

       read(2), pread(2), write(2), pwrite(2), lseek(2)
              These  operate  as  documented, with the exception that seek(2),
              write(2) and pwrite(2) are not supported beyond the end  of  the
              file. The file size is the size of the local storage of the SPU,
              which normally is 256 kilobytes.

       mmap(2)
              Mapping mem into the process address space gives access  to  the
              SPU  local  storage  within  the  process  address  space.  Only
              MAP_SHARED mappings are allowed.

   /mbox
       The first SPU to CPU communication mailbox. This file is read-only  and
       can  be  read  in  units of 32 bits.  The file can only be used in non-
       blocking mode and it even poll() will not block on  it.   The  possible
       operations on an open mbox file are:

       read(2)
              If  a  count smaller than four is requested, read returns -1 and
              sets errno to EINVAL.  If there is no data available in the mail
              box,  the  return  value  is set to -1 and errno becomes EAGAIN.
              When data has been read successfully, four bytes are  placed  in
              the data buffer and the value four is returned.

   /ibox
       The  second  SPU  to CPU communication mailbox. This file is similar to
       the first mailbox file, but can be read in blocking I/O mode,  and  the
       poll  family of system calls can be used to wait for it.  The  possible
       operations on an open ibox file are:

       read(2)
              If a count smaller than four is requested, read returns  -1  and
              sets errno to EINVAL.  If there is no data available in the mail
              box and the file descriptor has been opened with O_NONBLOCK, the
              return value is set to -1 and errno becomes EAGAIN.

              If  there  is  no  data  available  in the mail box and the file
              descriptor has been opened without  O_NONBLOCK,  the  call  will
              block  until  the  SPU  writes to its interrupt mailbox channel.
              When data has been read successfully, four bytes are  placed  in
              the data buffer and the value four is returned.

       poll(2)
              Poll  on  the  ibox  file returns (POLLIN | POLLRDNORM) whenever
              data is available for reading.

   /wbox
       The CPU to SPU communation mailbox. It is write-only and can be written
       in  units  of  32  bits. If the mailbox is full, write() will block and
       poll can be used to wait for it becoming  empty  again.   The  possible
       operations  on  an open wbox file are: write(2) If a count smaller than
       four is requested, write returns -1 and sets errno to EINVAL.  If there
       is  no space available in the mail box and the file descriptor has been
       opened with O_NONBLOCK, the return value is set to -1 and errno becomes
       EAGAIN.

       If  there is no space available in the mail box and the file descriptor
       has been opened without O_NONBLOCK, the call will block until  the  SPU
       reads  from  its PPE mailbox channel.  When data has been read success-
       fully, four bytes are placed in the data buffer and the value  four  is
       returned.

       poll(2)
              Poll  on  the  ibox file returns (POLLOUT | POLLWRNORM) whenever
              space is available for writing.

   /mbox_stat, /ibox_stat, /wbox_stat
       Read-only files that contain the length of the current queue, i.e.  how
       many  words  can  be  read  from  mbox or ibox or how many words can be
       written to wbox without blocking.  The files can be read only in 4-byte
       units  and  return  a  big-endian  binary integer number.  The possible
       operations on an open ``*box_stat`` file are:

       read(2)
              If a count smaller than four is requested, read returns  -1  and
              sets errno to EINVAL.  Otherwise, a four byte value is placed in
              the data buffer, containing the number of elements that  can  be
              read  from  (for  mbox_stat  and  ibox_stat)  or written to (for
              wbox_stat) the respective mail box without blocking or resulting
              in EAGAIN.

   /npc, /decr, /decr_status, /spu_tag_mask, /event_mask, /srr0
       Internal  registers  of  the SPU. The representation is an ASCII string
       with the numeric value of the next instruction to  be  executed.  These
       can  be  used in read/write mode for debugging, but normal operation of
       programs should not rely on them because access to any of  them  except
       npc requires an SPU context save and is therefore very inefficient.

       The contents of these files are:

       =================== ===================================
       npc                 Next Program Counter
       decr                SPU Decrementer
       decr_status         Decrementer Status
       spu_tag_mask        MFC tag mask for SPU DMA
       event_mask          Event mask for SPU interrupts
       srr0                Interrupt Return address register
       =================== ===================================

       The   possible   operations   on   an   open  npc,  decr,  decr_status,
       spu_tag_mask, event_mask or srr0 file are:

       read(2)
              When the count supplied to the read call  is  shorter  than  the
              required  length for the pointer value plus a newline character,
              subsequent reads from the same file descriptor  will  result  in
              completing  the string, regardless of changes to the register by
              a running SPU task.  When a complete string has been  read,  all
              subsequent read operations will return zero bytes and a new file
              descriptor needs to be opened to read the value again.

       write(2)
              A write operation on the file results in setting the register to
              the  value  given  in  the string. The string is parsed from the
              beginning to the first non-numeric character or the end  of  the
              buffer.  Subsequent writes to the same file descriptor overwrite
              the previous setting.

   /fpcr
       This file gives access to the Floating Point Status and Control  Regis-
       ter as a four byte long file. The operations on the fpcr file are:

       read(2)
              If  a  count smaller than four is requested, read returns -1 and
              sets errno to EINVAL.  Otherwise, a four byte value is placed in
              the data buffer, containing the current value of the fpcr regis-
              ter.

       write(2)
              If a count smaller than four is requested, write returns -1  and
              sets  errno  to  EINVAL.  Otherwise, a four byte value is copied
              from the data buffer, updating the value of the fpcr register.

   /signal1, /signal2
       The two signal notification channels of an SPU.  These  are  read-write
       files  that  operate  on  a 32 bit word.  Writing to one of these files
       triggers an interrupt on the SPU.  The  value  written  to  the  signal
       files can be read from the SPU through a channel read or from host user
       space through the file.  After the value has been read by the  SPU,  it
       is  reset  to zero.  The possible operations on an open signal1 or sig-
       nal2 file are:

       read(2)
              If a count smaller than four is requested, read returns  -1  and
              sets errno to EINVAL.  Otherwise, a four byte value is placed in
              the data buffer, containing the current value of  the  specified
              signal notification register.

       write(2)
              If  a count smaller than four is requested, write returns -1 and
              sets errno to EINVAL.  Otherwise, a four byte  value  is  copied
              from the data buffer, updating the value of the specified signal
              notification register.  The signal  notification  register  will
              either be replaced with the input data or will be updated to the
              bitwise OR of the old value and the input data, depending on the
              contents  of  the  signal1_type,  or  signal2_type respectively,
              file.

   /signal1_type, /signal2_type
       These two files change the behavior of the signal1 and signal2  notifi-
       cation  files.  The  contain  a numerical ASCII string which is read as
       either "1" or "0".  In mode 0 (overwrite), the  hardware  replaces  the
       contents of the signal channel with the data that is written to it.  in
       mode 1 (logical OR), the hardware accumulates the bits that are  subse-
       quently written to it.  The possible operations on an open signal1_type
       or signal2_type file are:

       read(2)
              When the count supplied to the read call  is  shorter  than  the
              required  length  for the digit plus a newline character, subse-
              quent reads from the same file descriptor will  result  in  com-
              pleting  the  string.  When a complete string has been read, all
              subsequent read operations will return zero bytes and a new file
              descriptor needs to be opened to read the value again.

       write(2)
              A write operation on the file results in setting the register to
              the value given in the string. The string  is  parsed  from  the
              beginning  to  the first non-numeric character or the end of the
              buffer.  Subsequent writes to the same file descriptor overwrite
              the previous setting.

Examples
========
       /etc/fstab entry
              none      /spu      spufs     gid=spu   0    0

Authors
=======
       Arnd  Bergmann  <arndb@de.ibm.com>,  Mark  Nutter <mnutter@us.ibm.com>,
       Ulrich Weigand <Ulrich.Weigand@de.ibm.com>

See Also
========
       capabilities(7), close(2), spu_create(2), spu_run(2), spufs(7)


code:
.. SPDX-License-Identifier: GPL-2.0

=======================
Squashfs 4.0 Filesystem
=======================

Squashfs is a compressed read-only filesystem for Linux.

It uses zlib, lz4, lzo, or xz compression to compress files, inodes and
directories.  Inodes in the system are very small and all blocks are packed to
minimise data overhead. Block sizes greater than 4K are supported up to a
maximum of 1Mbytes (default block size 128K).

Squashfs is intended for general read-only filesystem use, for archival
use (i.e. in cases where a .tar.gz file may be used), and in constrained
block device/memory systems (e.g. embedded systems) where low overhead is
needed.

Mailing list: squashfs-devel@lists.sourceforge.net
Web site: www.squashfs.org

1. Filesystem Features
----------------------

Squashfs filesystem features versus Cramfs:

============================== 	=========		==========
				Squashfs		Cramfs
============================== 	=========		==========
Max filesystem size		2^64			256 MiB
Max file size			~ 2 TiB			16 MiB
Max files			unlimited		unlimited
Max directories			unlimited		unlimited
Max entries per directory	unlimited		unlimited
Max block size			1 MiB			4 KiB
Metadata compression		yes			no
Directory indexes		yes			no
Sparse file support		yes			no
Tail-end packing (fragments)	yes			no
Exportable (NFS etc.)		yes			no
Hard link support		yes			no
"." and ".." in readdir		yes			no
Real inode numbers		yes			no
32-bit uids/gids		yes			no
File creation time		yes			no
Xattr support			yes			no
ACL support			no			no
============================== 	=========		==========

Squashfs compresses data, inodes and directories.  In addition, inode and
directory data are highly compacted, and packed on byte boundaries.  Each
compressed inode is on average 8 bytes in length (the exact length varies on
file type, i.e. regular file, directory, symbolic link, and block/char device
inodes have different sizes).

2. Using Squashfs
-----------------

As squashfs is a read-only filesystem, the mksquashfs program must be used to
create populated squashfs filesystems.  This and other squashfs utilities
can be obtained from http://www.squashfs.org.  Usage instructions can be
obtained from this site also.

The squashfs-tools development tree is now located on kernel.org
	git://git.kernel.org/pub/scm/fs/squashfs/squashfs-tools.git

3. Squashfs Filesystem Design
-----------------------------

A squashfs filesystem consists of a maximum of nine parts, packed together on a
byte alignment::

	 ---------------
	|  superblock 	|
	|---------------|
	|  compression  |
	|    options    |
	|---------------|
	|  datablocks   |
	|  & fragments  |
	|---------------|
	|  inode table	|
	|---------------|
	|   directory	|
	|     table     |
	|---------------|
	|   fragment	|
	|    table      |
	|---------------|
	|    export     |
	|    table      |
	|---------------|
	|    uid/gid	|
	|  lookup table	|
	|---------------|
	|     xattr     |
	|     table	|
	 ---------------

Compressed data blocks are written to the filesystem as files are read from
the source directory, and checked for duplicates.  Once all file data has been
written the completed inode, directory, fragment, export, uid/gid lookup and
xattr tables are written.

3.1 Compression options
-----------------------

Compressors can optionally support compression specific options (e.g.
dictionary size).  If non-default compression options have been used, then
these are stored here.

3.2 Inodes
----------

Metadata (inodes and directories) are compressed in 8Kbyte blocks.  Each
compressed block is prefixed by a two byte length, the top bit is set if the
block is uncompressed.  A block will be uncompressed if the -noI option is set,
or if the compressed block was larger than the uncompressed block.

Inodes are packed into the metadata blocks, and are not aligned to block
boundaries, therefore inodes overlap compressed blocks.  Inodes are identified
by a 48-bit number which encodes the location of the compressed metadata block
containing the inode, and the byte offset into that block where the inode is
placed (<block, offset>).

To maximise compression there are different inodes for each file type
(regular file, directory, device, etc.), the inode contents and length
varying with the type.

To further maximise compression, two types of regular file inode and
directory inode are defined: inodes optimised for frequently occurring
regular files and directories, and extended types where extra
information has to be stored.

3.3 Directories
---------------

Like inodes, directories are packed into compressed metadata blocks, stored
in a directory table.  Directories are accessed using the start address of
the metablock containing the directory and the offset into the
decompressed block (<block, offset>).

Directories are organised in a slightly complex way, and are not simply
a list of file names.  The organisation takes advantage of the
fact that (in most cases) the inodes of the files will be in the same
compressed metadata block, and therefore, can share the start block.
Directories are therefore organised in a two level list, a directory
header containing the shared start block value, and a sequence of directory
entries, each of which share the shared start block.  A new directory header
is written once/if the inode start block changes.  The directory
header/directory entry list is repeated as many times as necessary.

Directories are sorted, and can contain a directory index to speed up
file lookup.  Directory indexes store one entry per metablock, each entry
storing the index/filename mapping to the first directory header
in each metadata block.  Directories are sorted in alphabetical order,
and at lookup the index is scanned linearly looking for the first filename
alphabetically larger than the filename being looked up.  At this point the
location of the metadata block the filename is in has been found.
The general idea of the index is to ensure only one metadata block needs to be
decompressed to do a lookup irrespective of the length of the directory.
This scheme has the advantage that it doesn't require extra memory overhead
and doesn't require much extra storage on disk.

3.4 File data
-------------

Regular files consist of a sequence of contiguous compressed blocks, and/or a
compressed fragment block (tail-end packed block).   The compressed size
of each datablock is stored in a block list contained within the
file inode.

To speed up access to datablocks when reading 'large' files (256 Mbytes or
larger), the code implements an index cache that caches the mapping from
block index to datablock location on disk.

The index cache allows Squashfs to handle large files (up to 1.75 TiB) while
retaining a simple and space-efficient block list on disk.  The cache
is split into slots, caching up to eight 224 GiB files (128 KiB blocks).
Larger files use multiple slots, with 1.75 TiB files using all 8 slots.
The index cache is designed to be memory efficient, and by default uses
16 KiB.

3.5 Fragment lookup table
-------------------------

Regular files can contain a fragment index which is mapped to a fragment
location on disk and compressed size using a fragment lookup table.  This
fragment lookup table is itself stored compressed into metadata blocks.
A second index table is used to locate these.  This second index table for
speed of access (and because it is small) is read at mount time and cached
in memory.

3.6 Uid/gid lookup table
------------------------

For space efficiency regular files store uid and gid indexes, which are
converted to 32-bit uids/gids using an id look up table.  This table is
stored compressed into metadata blocks.  A second index table is used to
locate these.  This second index table for speed of access (and because it
is small) is read at mount time and cached in memory.

3.7 Export table
----------------

To enable Squashfs filesystems to be exportable (via NFS etc.) filesystems
can optionally (disabled with the -no-exports Mksquashfs option) contain
an inode number to inode disk location lookup table.  This is required to
enable Squashfs to map inode numbers passed in filehandles to the inode
location on disk, which is necessary when the export code reinstantiates
expired/flushed inodes.

This table is stored compressed into metadata blocks.  A second index table is
used to locate these.  This second index table for speed of access (and because
it is small) is read at mount time and cached in memory.

3.8 Xattr table
---------------

The xattr table contains extended attributes for each inode.  The xattrs
for each inode are stored in a list, each list entry containing a type,
name and value field.  The type field encodes the xattr prefix
("user.", "trusted." etc) and it also encodes how the name/value fields
should be interpreted.  Currently the type indicates whether the value
is stored inline (in which case the value field contains the xattr value),
or if it is stored out of line (in which case the value field stores a
reference to where the actual value is stored).  This allows large values
to be stored out of line improving scanning and lookup performance and it
also allows values to be de-duplicated, the value being stored once, and
all other occurrences holding an out of line reference to that value.

The xattr lists are packed into compressed 8K metadata blocks.
To reduce overhead in inodes, rather than storing the on-disk
location of the xattr list inside each inode, a 32-bit xattr id
is stored.  This xattr id is mapped into the location of the xattr
list using a second xattr id lookup table.

4. TODOs and Outstanding Issues
-------------------------------

4.1 TODO list
-------------

Implement ACL support.

4.2 Squashfs Internal Cache
---------------------------

Blocks in Squashfs are compressed.  To avoid repeatedly decompressing
recently accessed data Squashfs uses two small metadata and fragment caches.

The cache is not used for file datablocks, these are decompressed and cached in
the page-cache in the normal way.  The cache is used to temporarily cache
fragment and metadata blocks which have been read as a result of a metadata
(i.e. inode or directory) or fragment access.  Because metadata and fragments
are packed together into blocks (to gain greater compression) the read of a
particular piece of metadata or fragment will retrieve other metadata/fragments
which have been packed with it, these because of locality-of-reference may be
read in the near future. Temporarily caching them ensures they are available
for near future access without requiring an additional read and decompress.

In the future this internal cache may be replaced with an implementation which
uses the kernel page cache.  Because the page cache operates on page sized
units this may introduce additional complexity in terms of locking and
associated race conditions.


code:
.. SPDX-License-Identifier: GPL-2.0

=====================================================
sysfs - _The_ filesystem for exporting kernel objects
=====================================================

Patrick Mochel	<mochel@osdl.org>

Mike Murphy <mamurph@cs.clemson.edu>

:Revised:    16 August 2011
:Original:   10 January 2003

What it is
~~~~~~~~~~

sysfs is a RAM-based filesystem initially based on ramfs. It provides
a means to export kernel data structures, their attributes, and the
linkages between them to userspace.

sysfs is tied inherently to the kobject infrastructure. Please read
Documentation/core-api/kobject.rst for more information concerning the kobject
interface.

Using sysfs
~~~~~~~~~~~

sysfs is always compiled in if CONFIG_SYSFS is defined. You can access
it by doing::

    mount -t sysfs sysfs /sys

Directory Creation
~~~~~~~~~~~~~~~~~~

For every kobject that is registered with the system, a directory is
created for it in sysfs. That directory is created as a subdirectory
of the kobject's parent, expressing internal object hierarchies to
userspace. Top-level directories in sysfs represent the common
ancestors of object hierarchies; i.e. the subsystems the objects
belong to.

sysfs internally stores a pointer to the kobject that implements a
directory in the kernfs_node object associated with the directory. In
the past this kobject pointer has been used by sysfs to do reference
counting directly on the kobject whenever the file is opened or closed.
With the current sysfs implementation the kobject reference count is
only modified directly by the function sysfs_schedule_callback().

Attributes
~~~~~~~~~~

Attributes can be exported for kobjects in the form of regular files in
the filesystem. sysfs forwards file I/O operations to methods defined
for the attributes, providing a means to read and write kernel
attributes.

Attributes should be ASCII text files, preferably with only one value
per file. It is noted that it may not be efficient to contain only one
value per file, so it is socially acceptable to express an array of
values of the same type.

Mixing types, expressing multiple lines of data, and doing fancy
formatting of data is heavily frowned upon. Doing these things may get
you publicly humiliated and your code rewritten without notice.

An attribute definition is simply::

    struct attribute {
	    char                    *name;
	    struct module           *owner;
	    umode_t                 mode;
    };

    int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
    void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);

A bare attribute contains no means to read or write the value of the
attribute. Subsystems are encouraged to define their own attribute
structure and wrapper functions for adding and removing attributes for
a specific object type.

For example, the driver model defines struct device_attribute like::

    struct device_attribute {
	    struct attribute	attr;
	    ssize_t (*show)(struct device *dev, struct device_attribute *attr,
			    char *buf);
	    ssize_t (*store)(struct device *dev, struct device_attribute *attr,
			    const char *buf, size_t count);
    };

    int device_create_file(struct device *, const struct device_attribute *);
    void device_remove_file(struct device *, const struct device_attribute *);

It also defines this helper for defining device attributes::

    #define DEVICE_ATTR(_name, _mode, _show, _store) \
    struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

For example, declaring::

    static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);

is equivalent to doing::

    static struct device_attribute dev_attr_foo = {
	    .attr = {
		    .name = "foo",
		    .mode = S_IWUSR | S_IRUGO,
	    },
	    .show = show_foo,
	    .store = store_foo,
    };

Note as stated in include/linux/kernel.h "OTHER_WRITABLE?  Generally
considered a bad idea." so trying to set a sysfs file writable for
everyone will fail reverting to RO mode for "Others".

For the common cases sysfs.h provides convenience macros to make
defining attributes easier as well as making code more concise and
readable. The above case could be shortened to:

static struct device_attribute dev_attr_foo = __ATTR_RW(foo);

the list of helpers available to define your wrapper function is:

__ATTR_RO(name):
		 assumes default name_show and mode 0444
__ATTR_WO(name):
		 assumes a name_store only and is restricted to mode
                 0200 that is root write access only.
__ATTR_RO_MODE(name, mode):
	         for more restrictive RO access; currently
                 only use case is the EFI System Resource Table
                 (see drivers/firmware/efi/esrt.c)
__ATTR_RW(name):
	         assumes default name_show, name_store and setting
                 mode to 0644.
__ATTR_NULL:
	         which sets the name to NULL and is used as end of list
                 indicator (see: kernel/workqueue.c)

Subsystem-Specific Callbacks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When a subsystem defines a new attribute type, it must implement a
set of sysfs operations for forwarding read and write calls to the
show and store methods of the attribute owners::

    struct sysfs_ops {
	    ssize_t (*show)(struct kobject *, struct attribute *, char *);
	    ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
    };

[ Subsystems should have already defined a struct kobj_type as a
descriptor for this type, which is where the sysfs_ops pointer is
stored. See the kobject documentation for more information. ]

When a file is read or written, sysfs calls the appropriate method
for the type. The method then translates the generic struct kobject
and struct attribute pointers to the appropriate pointer types, and
calls the associated methods.

To illustrate::

    #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)

    static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
				char *buf)
    {
	    struct device_attribute *dev_attr = to_dev_attr(attr);
	    struct device *dev = kobj_to_dev(kobj);
	    ssize_t ret = -EIO;

	    if (dev_attr->show)
		    ret = dev_attr->show(dev, dev_attr, buf);
	    if (ret >= (ssize_t)PAGE_SIZE) {
		    printk("dev_attr_show: %pS returned bad count\n",
				    dev_attr->show);
	    }
	    return ret;
    }

Reading/Writing Attribute Data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To read or write attributes, show() or store() methods must be
specified when declaring the attribute. The method types should be as
simple as those defined for device attributes::

    ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
    ssize_t (*store)(struct device *dev, struct device_attribute *attr,
		    const char *buf, size_t count);

IOW, they should take only an object, an attribute, and a buffer as parameters.

sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
method. sysfs will call the method exactly once for each read or
write. This forces the following behavior on the method
implementations:

- On read(2), the show() method should fill the entire buffer.
  Recall that an attribute should only be exporting one value, or an
  array of similar values, so this shouldn't be that expensive.

  This allows userspace to do partial reads and forward seeks
  arbitrarily over the entire file at will. If userspace seeks back to
  zero or does a pread(2) with an offset of '0' the show() method will
  be called again, rearmed, to fill the buffer.

- On write(2), sysfs expects the entire buffer to be passed during the
  first write. sysfs then passes the entire buffer to the store() method.
  A terminating null is added after the data on stores. This makes
  functions like sysfs_streq() safe to use.

  When writing sysfs files, userspace processes should first read the
  entire file, modify the values it wishes to change, then write the
  entire buffer back.

  Attribute method implementations should operate on an identical
  buffer when reading and writing values.

Other notes:

- Writing causes the show() method to be rearmed regardless of current
  file position.

- The buffer will always be PAGE_SIZE bytes in length. On x86, this
  is 4096.

- show() methods should return the number of bytes printed into the
  buffer.

- show() should only use sysfs_emit() or sysfs_emit_at() when formatting
  the value to be returned to user space.

- store() should return the number of bytes used from the buffer. If the
  entire buffer has been used, just return the count argument.

- show() or store() can always return errors. If a bad value comes
  through, be sure to return an error.

- The object passed to the methods will be pinned in memory via sysfs
  reference counting its embedded object. However, the physical
  entity (e.g. device) the object represents may not be present. Be
  sure to have a way to check this, if necessary.

A very simple (and naive) implementation of a device attribute is::

    static ssize_t show_name(struct device *dev, struct device_attribute *attr,
			    char *buf)
    {
	    return sysfs_emit(buf, "%s\n", dev->name);
    }

    static ssize_t store_name(struct device *dev, struct device_attribute *attr,
			    const char *buf, size_t count)
    {
	    snprintf(dev->name, sizeof(dev->name), "%.*s",
		    (int)min(count, sizeof(dev->name) - 1), buf);
	    return count;
    }

    static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);

(Note that the real implementation doesn't allow userspace to set the
name for a device.)

Top Level Directory Layout
~~~~~~~~~~~~~~~~~~~~~~~~~~

The sysfs directory arrangement exposes the relationship of kernel
data structures.

The top level sysfs directory looks like::

    block/
    bus/
    class/
    dev/
    devices/
    firmware/
    fs/
    hypervisor/
    kernel/
    module/
    net/
    power/

devices/ contains a filesystem representation of the device tree. It maps
directly to the internal kernel device tree, which is a hierarchy of
struct device.

bus/ contains flat directory layout of the various bus types in the
kernel. Each bus's directory contains two subdirectories::

	devices/
	drivers/

devices/ contains symlinks for each device discovered in the system
that point to the device's directory under root/.

drivers/ contains a directory for each device driver that is loaded
for devices on that particular bus (this assumes that drivers do not
span multiple bus types).

fs/ contains a directory for some filesystems.  Currently each
filesystem wanting to export attributes must create its own hierarchy
below fs/ (see ./fuse.rst for an example).

module/ contains parameter values and state information for all
loaded system modules, for both builtin and loadable modules.

dev/ contains two directories: char/ and block/. Inside these two
directories there are symlinks named <major>:<minor>.  These symlinks
point to the sysfs directory for the given device.  /sys/dev provides a
quick way to lookup the sysfs interface for a device from the result of
a stat(2) operation.

More information on driver-model specific features can be found in
Documentation/driver-api/driver-model/.

TODO: Finish this section.

Current Interfaces
~~~~~~~~~~~~~~~~~~

The following interface layers currently exist in sysfs.

devices (include/linux/device.h)
--------------------------------
Structure::

    struct device_attribute {
	    struct attribute	attr;
	    ssize_t (*show)(struct device *dev, struct device_attribute *attr,
			    char *buf);
	    ssize_t (*store)(struct device *dev, struct device_attribute *attr,
			    const char *buf, size_t count);
    };

Declaring::

    DEVICE_ATTR(_name, _mode, _show, _store);

Creation/Removal::

    int device_create_file(struct device *dev, const struct device_attribute * attr);
    void device_remove_file(struct device *dev, const struct device_attribute * attr);

bus drivers (include/linux/device.h)
------------------------------------
Structure::

    struct bus_attribute {
	    struct attribute        attr;
	    ssize_t (*show)(struct bus_type *, char * buf);
	    ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
    };

Declaring::

    static BUS_ATTR_RW(name);
    static BUS_ATTR_RO(name);
    static BUS_ATTR_WO(name);

Creation/Removal::

    int bus_create_file(struct bus_type *, struct bus_attribute *);
    void bus_remove_file(struct bus_type *, struct bus_attribute *);

device drivers (include/linux/device.h)
---------------------------------------

Structure::

    struct driver_attribute {
	    struct attribute        attr;
	    ssize_t (*show)(struct device_driver *, char * buf);
	    ssize_t (*store)(struct device_driver *, const char * buf,
			    size_t count);
    };

Declaring::

    DRIVER_ATTR_RO(_name)
    DRIVER_ATTR_RW(_name)

Creation/Removal::

    int driver_create_file(struct device_driver *, const struct driver_attribute *);
    void driver_remove_file(struct device_driver *, const struct driver_attribute *);

Documentation
~~~~~~~~~~~~~

The sysfs directory structure and the attributes in each directory define an
ABI between the kernel and user space. As for any ABI, it is important that
this ABI is stable and properly documented. All new sysfs attributes must be
documented in Documentation/ABI. See also Documentation/ABI/README for more
information.


code:
.. SPDX-License-Identifier: GPL-2.0

==================
SystemV Filesystem
==================

It implements all of
  - Xenix FS,
  - SystemV/386 FS,
  - Coherent FS.

To install:

* Answer the 'System V and Coherent filesystem support' question with 'y'
  when configuring the kernel.
* To mount a disk or a partition, use::

    mount [-r] -t sysv device mountpoint

  The file system type names::

               -t sysv
               -t xenix
               -t coherent

  may be used interchangeably, but the last two will eventually disappear.

Bugs in the present implementation:

- Coherent FS:

  - The "free list interleave" n:m is currently ignored.
  - Only file systems with no filesystem name and no pack name are recognized.
    (See Coherent "man mkfs" for a description of these features.)

- SystemV Release 2 FS:

  The superblock is only searched in the blocks 9, 15, 18, which
  corresponds to the beginning of track 1 on floppy disks. No support
  for this FS on hard disk yet.

These filesystems are rather similar. Here is a comparison with Minix FS:

* Linux fdisk reports on partitions

  - Minix FS     0x81 Linux/Minix
  - Xenix FS     ??
  - SystemV FS   ??
  - Coherent FS  0x08 AIX bootable

* Size of a block or zone (data allocation unit on disk)

  - Minix FS     1024
  - Xenix FS     1024 (also 512 ??)
  - SystemV FS   1024 (also 512 and 2048)
  - Coherent FS   512

* General layout: all have one boot block, one super block and
  separate areas for inodes and for directories/data.
  On SystemV Release 2 FS (e.g. Microport) the first track is reserved and
  all the block numbers (including the super block) are offset by one track.

* Byte ordering of "short" (16 bit entities) on disk:

  - Minix FS     little endian  0 1
  - Xenix FS     little endian  0 1
  - SystemV FS   little endian  0 1
  - Coherent FS  little endian  0 1

  Of course, this affects only the file system, not the data of files on it!

* Byte ordering of "long" (32 bit entities) on disk:

  - Minix FS     little endian  0 1 2 3
  - Xenix FS     little endian  0 1 2 3
  - SystemV FS   little endian  0 1 2 3
  - Coherent FS  PDP-11         2 3 0 1

  Of course, this affects only the file system, not the data of files on it!

* Inode on disk: "short", 0 means non-existent, the root dir ino is:

  =================================  ==
  Minix FS                            1
  Xenix FS, SystemV FS, Coherent FS   2
  =================================  ==

* Maximum number of hard links to a file:

  ===========  =========
  Minix FS     250
  Xenix FS     ??
  SystemV FS   ??
  Coherent FS  >=10000
  ===========  =========

* Free inode management:

  - Minix FS
      a bitmap
  - Xenix FS, SystemV FS, Coherent FS
      There is a cache of a certain number of free inodes in the super-block.
      When it is exhausted, new free inodes are found using a linear search.

* Free block management:

  - Minix FS
      a bitmap
  - Xenix FS, SystemV FS, Coherent FS
      Free blocks are organized in a "free list". Maybe a misleading term,
      since it is not true that every free block contains a pointer to
      the next free block. Rather, the free blocks are organized in chunks
      of limited size, and every now and then a free block contains pointers
      to the free blocks pertaining to the next chunk; the first of these
      contains pointers and so on. The list terminates with a "block number"
      0 on Xenix FS and SystemV FS, with a block zeroed out on Coherent FS.

* Super-block location:

  ===========  ==========================
  Minix FS     block 1 = bytes 1024..2047
  Xenix FS     block 1 = bytes 1024..2047
  SystemV FS   bytes 512..1023
  Coherent FS  block 1 = bytes 512..1023
  ===========  ==========================

* Super-block layout:

  - Minix FS::

                    unsigned short s_ninodes;
                    unsigned short s_nzones;
                    unsigned short s_imap_blocks;
                    unsigned short s_zmap_blocks;
                    unsigned short s_firstdatazone;
                    unsigned short s_log_zone_size;
                    unsigned long s_max_size;
                    unsigned short s_magic;

  - Xenix FS, SystemV FS, Coherent FS::

                    unsigned short s_firstdatazone;
                    unsigned long  s_nzones;
                    unsigned short s_fzone_count;
                    unsigned long  s_fzones[NICFREE];
                    unsigned short s_finode_count;
                    unsigned short s_finodes[NICINOD];
                    char           s_flock;
                    char           s_ilock;
                    char           s_modified;
                    char           s_rdonly;
                    unsigned long  s_time;
                    short          s_dinfo[4]; -- SystemV FS only
                    unsigned long  s_free_zones;
                    unsigned short s_free_inodes;
                    short          s_dinfo[4]; -- Xenix FS only
                    unsigned short s_interleave_m,s_interleave_n; -- Coherent FS only
                    char           s_fname[6];
                    char           s_fpack[6];

    then they differ considerably:

        Xenix FS::

                    char           s_clean;
                    char           s_fill[371];
                    long           s_magic;
                    long           s_type;

        SystemV FS::

                    long           s_fill[12 or 14];
                    long           s_state;
                    long           s_magic;
                    long           s_type;

        Coherent FS::

                    unsigned long  s_unique;

    Note that Coherent FS has no magic.

* Inode layout:

  - Minix FS::

                    unsigned short i_mode;
                    unsigned short i_uid;
                    unsigned long  i_size;
                    unsigned long  i_time;
                    unsigned char  i_gid;
                    unsigned char  i_nlinks;
                    unsigned short i_zone[7+1+1];

  - Xenix FS, SystemV FS, Coherent FS::

                    unsigned short i_mode;
                    unsigned short i_nlink;
                    unsigned short i_uid;
                    unsigned short i_gid;
                    unsigned long  i_size;
                    unsigned char  i_zone[3*(10+1+1+1)];
                    unsigned long  i_atime;
                    unsigned long  i_mtime;
                    unsigned long  i_ctime;

* Regular file data blocks are organized as

  - Minix FS:

             - 7 direct blocks
	     - 1 indirect block (pointers to blocks)
             - 1 double-indirect block (pointer to pointers to blocks)

  - Xenix FS, SystemV FS, Coherent FS:

             - 10 direct blocks
             -  1 indirect block (pointers to blocks)
             -  1 double-indirect block (pointer to pointers to blocks)
             -  1 triple-indirect block (pointer to pointers to pointers to blocks)

  ===========  ==========   ================
               Inode size   inodes per block
  ===========  ==========   ================
  Minix FS        32        32
  Xenix FS        64        16
  SystemV FS      64        16
  Coherent FS     64        8
  ===========  ==========   ================

* Directory entry on disk

  - Minix FS::

                    unsigned short inode;
                    char name[14/30];

  - Xenix FS, SystemV FS, Coherent FS::

                    unsigned short inode;
                    char name[14];

  ===========    ==============    =====================
                 Dir entry size    dir entries per block
  ===========    ==============    =====================
  Minix FS       16/32             64/32
  Xenix FS       16                64
  SystemV FS     16                64
  Coherent FS    16                32
  ===========    ==============    =====================

* How to implement symbolic links such that the host fsck doesn't scream:

  - Minix FS     normal
  - Xenix FS     kludge: as regular files with  chmod 1000
  - SystemV FS   ??
  - Coherent FS  kludge: as regular files with  chmod 1000

Notation: We often speak of a "block" but mean a zone (the allocation unit)
and not the disk driver's notion of "block".


code:
.. SPDX-License-Identifier: GPL-2.0

=====
Tmpfs
=====

Tmpfs is a file system which keeps all of its files in virtual memory.

Everything in tmpfs is temporary in the sense that no files will be
created on your hard drive. If you unmount a tmpfs instance,
everything stored therein is lost.

tmpfs puts everything into the kernel internal caches and grows and
shrinks to accommodate the files it contains and is able to swap
unneeded pages out to swap space. It has maximum size limits which can
be adjusted on the fly via 'mount -o remount ...'

If you compare it to ramfs (which was the template to create tmpfs)
you gain swapping and limit checking. Another similar thing is the RAM
disk (/dev/ram*), which simulates a fixed size hard disk in physical
RAM, where you have to create an ordinary filesystem on top. Ramdisks
cannot swap and you do not have the possibility to resize them.

Since tmpfs lives completely in the page cache and on swap, all tmpfs
pages will be shown as "Shmem" in /proc/meminfo and "Shared" in
free(1). Notice that these counters also include shared memory
(shmem, see ipcs(1)). The most reliable way to get the count is
using df(1) and du(1).

tmpfs has the following uses:

1) There is always a kernel internal mount which you will not see at
   all. This is used for shared anonymous mappings and SYSV shared
   memory.

   This mount does not depend on CONFIG_TMPFS. If CONFIG_TMPFS is not
   set, the user visible part of tmpfs is not built. But the internal
   mechanisms are always present.

2) glibc 2.2 and above expects tmpfs to be mounted at /dev/shm for
   POSIX shared memory (shm_open, shm_unlink). Adding the following
   line to /etc/fstab should take care of this::

	tmpfs	/dev/shm	tmpfs	defaults	0 0

   Remember to create the directory that you intend to mount tmpfs on
   if necessary.

   This mount is _not_ needed for SYSV shared memory. The internal
   mount is used for that. (In the 2.3 kernel versions it was
   necessary to mount the predecessor of tmpfs (shm fs) to use SYSV
   shared memory.)

3) Some people (including me) find it very convenient to mount it
   e.g. on /tmp and /var/tmp and have a big swap partition. And now
   loop mounts of tmpfs files do work, so mkinitrd shipped by most
   distributions should succeed with a tmpfs /tmp.

4) And probably a lot more I do not know about :-)

tmpfs has three mount options for sizing:

=========  ============================================================
size       The limit of allocated bytes for this tmpfs instance. The
           default is half of your physical RAM without swap. If you
           oversize your tmpfs instances the machine will deadlock
           since the OOM handler will not be able to free that memory.
nr_blocks  The same as size, but in blocks of PAGE_SIZE.
nr_inodes  The maximum number of inodes for this instance. The default
           is half of the number of your physical RAM pages, or (on a
           machine with highmem) the number of lowmem RAM pages,
           whichever is the lower.
=========  ============================================================

These parameters accept a suffix k, m or g for kilo, mega and giga and
can be changed on remount.  The size parameter also accepts a suffix %
to limit this tmpfs instance to that percentage of your physical RAM:
the default, when neither size nor nr_blocks is specified, is size=50%

If nr_blocks=0 (or size=0), blocks will not be limited in that instance;
if nr_inodes=0, inodes will not be limited.  It is generally unwise to
mount with such options, since it allows any user with write access to
use up all the memory on the machine; but enhances the scalability of
that instance in a system with many CPUs making intensive use of it.

tmpfs has a mount option to set the NUMA memory allocation policy for
all files in that instance (if CONFIG_NUMA is enabled) - which can be
adjusted on the fly via 'mount -o remount ...'

======================== ==============================================
mpol=default             use the process allocation policy
                         (see set_mempolicy(2))
mpol=prefer:Node         prefers to allocate memory from the given Node
mpol=bind:NodeList       allocates memory only from nodes in NodeList
mpol=interleave          prefers to allocate from each node in turn
mpol=interleave:NodeList allocates from each node of NodeList in turn
mpol=local		 prefers to allocate memory from the local node
======================== ==============================================

NodeList format is a comma-separated list of decimal numbers and ranges,
a range being two hyphen-separated decimal numbers, the smallest and
largest node numbers in the range.  For example, mpol=bind:0-3,5,7,9-15

A memory policy with a valid NodeList will be saved, as specified, for
use at file creation time.  When a task allocates a file in the file
system, the mount option memory policy will be applied with a NodeList,
if any, modified by the calling task's cpuset constraints
[See Documentation/admin-guide/cgroup-v1/cpusets.rst] and any optional flags,
listed below.  If the resulting NodeLists is the empty set, the effective
memory policy for the file will revert to "default" policy.

NUMA memory allocation policies have optional flags that can be used in
conjunction with their modes.  These optional flags can be specified
when tmpfs is mounted by appending them to the mode before the NodeList.
See Documentation/admin-guide/mm/numa_memory_policy.rst for a list of
all available memory allocation policy mode flags and their effect on
memory policy.

::

	=static		is equivalent to	MPOL_F_STATIC_NODES
	=relative	is equivalent to	MPOL_F_RELATIVE_NODES

For example, mpol=bind=static:NodeList, is the equivalent of an
allocation policy of MPOL_BIND | MPOL_F_STATIC_NODES.

Note that trying to mount a tmpfs with an mpol option will fail if the
running kernel does not support NUMA; and will fail if its nodelist
specifies a node which is not online.  If your system relies on that
tmpfs being mounted, but from time to time runs a kernel built without
NUMA capability (perhaps a safe recovery kernel), or with fewer nodes
online, then it is advisable to omit the mpol option from automatic
mount options.  It can be added later, when the tmpfs is already mounted
on MountPoint, by 'mount -o remount,mpol=Policy:NodeList MountPoint'.

To specify the initial root directory you can use the following mount
options:

====	==================================
mode	The permissions as an octal number
uid	The user id
gid	The group id
====	==================================

These options do not have any effect on remount. You can change these
parameters with chmod(1), chown(1) and chgrp(1) on a mounted filesystem.

tmpfs has a mount option to select whether it will wrap at 32- or 64-bit inode
numbers:

=======   ========================
inode64   Use 64-bit inode numbers
inode32   Use 32-bit inode numbers
=======   ========================

On a 32-bit kernel, inode32 is implicit, and inode64 is refused at mount time.
On a 64-bit kernel, CONFIG_TMPFS_INODE64 sets the default.  inode64 avoids the
possibility of multiple files with the same inode number on a single device;
but risks glibc failing with EOVERFLOW once 33-bit inode numbers are reached -
if a long-lived tmpfs is accessed by 32-bit applications so ancient that
opening a file larger than 2GiB fails with EINVAL.

So 'mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs'
will give you tmpfs instance on /mytmpfs which can allocate 10GB
RAM/SWAP in 10240 inodes and it is only accessible by root.

:Author:
   Christoph Rohland <cr@sap.com>, 1.12.01
:Updated:
   Hugh Dickins, 4 June 2007
:Updated:
   KOSAKI Motohiro, 16 Mar 2010
:Updated:
   Chris Down, 13 July 2020