<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/linux.git/fs/nfs/dir.c, branch linux-6.0.y</title>
<subtitle>Linux kernel stable tree (mirror)</subtitle>
<id>https://git.radix-linux.su/kernel/linux.git/atom?h=linux-6.0.y</id>
<link rel='self' href='https://git.radix-linux.su/kernel/linux.git/atom?h=linux-6.0.y'/>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/'/>
<updated>2022-08-20T00:31:36+00:00</updated>
<entry>
<title>NFS: unlink/rmdir shouldn't call d_delete() twice on ENOENT</title>
<updated>2022-08-20T00:31:36+00:00</updated>
<author>
<name>NeilBrown</name>
<email>neilb@suse.de</email>
</author>
<published>2022-08-18T23:55:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=f16857e62bac60786104c020ad7c86e2163b2c5b'/>
<id>urn:sha1:f16857e62bac60786104c020ad7c86e2163b2c5b</id>
<content type='text'>
nfs_unlink() calls d_delete() twice if it receives ENOENT from the
server - once in nfs_dentry_handle_enoent() from nfs_safe_remove and
once in nfs_dentry_remove_handle_error().

nfs_rmddir() also calls it twice - the nfs_dentry_handle_enoent() call
is direct and inside a region locked with -&gt;rmdir_sem

It is safe to call d_delete() twice if the refcount &gt; 1 as the dentry is
simply unhashed.
If the refcount is 1, the first call sets d_inode to NULL and the second
call crashes.

This patch guards the d_delete() call from nfs_dentry_handle_enoent()
leaving the one under -&gt;remdir_sem in case that is important.

In mainline it would be safe to remove the d_delete() call.  However in
older kernels to which this might be backported, that would change the
behaviour of nfs_unlink().  nfs_unlink() used to unhash the dentry which
resulted in nfs_dentry_handle_enoent() not calling d_delete().  So in
older kernels we need the d_delete() in nfs_dentry_remove_handle_error()
when called from nfs_unlink() but not when called from nfs_rmdir().

To make the code work correctly for old and new kernels, and from both
nfs_unlink() and nfs_rmdir(), we protect the d_delete() call with
simple_positive().  This ensures it is never called in a circumstance
where it could crash.

Fixes: 3c59366c207e ("NFS: don't unhash dentry during unlink/rename")
Fixes: 9019fb391de0 ("NFS: Label the dentry with a verifier in nfs_rmdir() and nfs_unlink()")
Signed-off-by: NeilBrown &lt;neilb@suse.de&gt;
Tested-by: Olga Kornievskaia &lt;aglo@umich.edu&gt;
Signed-off-by: Trond Myklebust &lt;trond.myklebust@hammerspace.com&gt;
</content>
</entry>
<entry>
<title>NFS: Fix missing unlock in nfs_unlink()</title>
<updated>2022-08-13T17:02:13+00:00</updated>
<author>
<name>Sun Ke</name>
<email>sunke32@huawei.com</email>
</author>
<published>2022-08-12T01:14:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=2067231a9e2cbbcae0a4aca6ac36ff2dd6a7b701'/>
<id>urn:sha1:2067231a9e2cbbcae0a4aca6ac36ff2dd6a7b701</id>
<content type='text'>
Add the missing unlock before goto.

Fixes: 3c59366c207e ("NFS: don't unhash dentry during unlink/rename")
Signed-off-by: Sun Ke &lt;sunke32@huawei.com&gt;
Signed-off-by: Trond Myklebust &lt;trond.myklebust@hammerspace.com&gt;
</content>
</entry>
<entry>
<title>NFS: don't unhash dentry during unlink/rename</title>
<updated>2022-08-08T20:25:56+00:00</updated>
<author>
<name>NeilBrown</name>
<email>neilb@suse.de</email>
</author>
<published>2022-08-01T00:33:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=3c59366c207e4c6c6569524af606baf017a55c61'/>
<id>urn:sha1:3c59366c207e4c6c6569524af606baf017a55c61</id>
<content type='text'>
NFS unlink() (and rename over existing target) must determine if the
file is open, and must perform a "silly rename" instead of an unlink (or
before rename) if it is.  Otherwise the client might hold a file open
which has been removed on the server.

Consequently if it determines that the file isn't open, it must block
any subsequent opens until the unlink/rename has been completed on the
server.

This is currently achieved by unhashing the dentry.  This forces any
open attempt to the slow-path for lookup which will block on i_rwsem on
the directory until the unlink/rename completes.  A future patch will
change the VFS to only get a shared lock on i_rwsem for unlink, so this
will no longer work.

Instead we introduce an explicit interlock.  A special value is stored
in dentry-&gt;d_fsdata while the unlink/rename is running and
-&gt;d_revalidate blocks while that value is present.  When -&gt;d_revalidate
unblocks, the dentry will be invalid.  This closes the race
without requiring exclusion on i_rwsem.

d_fsdata is already used in two different ways.
1/ an IS_ROOT directory dentry might have a "devname" stored in
   d_fsdata.  Such a dentry doesn't have a name and so cannot be the
   target of unlink or rename.  For safety we check if an old devname
   is still stored, and remove it if it is.
2/ a dentry with DCACHE_NFSFS_RENAMED set will have a 'struct
   nfs_unlinkdata' stored in d_fsdata.  While this is set maydelete()
   will fail, so an unlink or rename will never proceed on such
   a dentry.

Neither of these can be in effect when a dentry is the target of unlink
or rename.  So we can expect d_fsdata to be NULL, and store a special
value ((void*)1) which is given the name NFS_FSDATA_BLOCKED to indicate
that any lookup will be blocked.

The d_count() is incremented under d_lock() when a lookup finds the
dentry, so we check d_count() is low, and set NFS_FSDATA_BLOCKED under
the same lock to avoid any races.

Signed-off-by: NeilBrown &lt;neilb@suse.de&gt;
Signed-off-by: Trond Myklebust &lt;trond.myklebust@hammerspace.com&gt;
</content>
</entry>
<entry>
<title>nfs: Replace kmap() with kmap_local_page()</title>
<updated>2022-07-12T14:06:18+00:00</updated>
<author>
<name>Fabio M. De Francesco</name>
<email>fmdefrancesco@gmail.com</email>
</author>
<published>2022-06-28T18:24:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=c77c738c37d0fa8380a671613630298d71099180'/>
<id>urn:sha1:c77c738c37d0fa8380a671613630298d71099180</id>
<content type='text'>
The use of kmap() is being deprecated in favor of kmap_local_page().

With kmap_local_page(), the mapping is per thread, CPU local and not
globally visible. Furthermore, the mapping can be acquired from any context
(including interrupts).

Therefore, use kmap_local_page() in nfs_do_filldir() because this mapping
is per thread, CPU local, and not globally visible.

Suggested-by: Ira Weiny &lt;ira.weiny@intel.com&gt;
Signed-off-by: Fabio M. De Francesco &lt;fmdefrancesco@gmail.com&gt;
Signed-off-by: Trond Myklebust &lt;trond.myklebust@hammerspace.com&gt;
</content>
</entry>
<entry>
<title>NFS: Fix case insensitive renames</title>
<updated>2022-07-10T23:00:53+00:00</updated>
<author>
<name>Trond Myklebust</name>
<email>trond.myklebust@hammerspace.com</email>
</author>
<published>2022-06-27T20:04:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=6ca0a6f834ed06b2b4c6d1f7f162f2b0d3e196cf'/>
<id>urn:sha1:6ca0a6f834ed06b2b4c6d1f7f162f2b0d3e196cf</id>
<content type='text'>
For filesystems that are case insensitive and case preserving, we need
to be able to rename from one case folded variant of the filename to
another.
Currently, if we have looked up the target filename before the call to
rename, then we may have a hashed dentry with that target name in the
dcache, causing the vfs to optimise away the rename.
To avoid that, let's drop the target dentry, and leave it to the server
to optimise away the rename if that is the correct thing to do.

Signed-off-by: Trond Myklebust &lt;trond.myklebust@hammerspace.com&gt;
</content>
</entry>
<entry>
<title>NFSv4: Add FMODE_CAN_ODIRECT after successful open of a NFS4.x file</title>
<updated>2022-06-15T19:03:12+00:00</updated>
<author>
<name>Dave Wysochanski</name>
<email>dwysocha@redhat.com</email>
</author>
<published>2022-06-10T00:46:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=5ee3d10f84d0a32fc11a55c70c204b6d81fd9ef6'/>
<id>urn:sha1:5ee3d10f84d0a32fc11a55c70c204b6d81fd9ef6</id>
<content type='text'>
Commit a2ad63daa88b ("VFS: add FMODE_CAN_ODIRECT file flag")
added the FMODE_CAN_ODIRECT flag for NFSv3 but neglected to add
it for NFSv4.x.  This causes direct io on NFSv4.x to fail open
with EINVAL:
  mount -o vers=4.2 127.0.0.1:/export /mnt/nfs4
  dd if=/dev/zero of=/mnt/nfs4/file.bin bs=128k count=1 oflag=direct
  dd: failed to open '/mnt/nfs4/file.bin': Invalid argument
  dd of=/dev/null if=/mnt/nfs4/file.bin bs=128k count=1 iflag=direct
  dd: failed to open '/mnt/dir1/file1.bin': Invalid argument

Fixes: a2ad63daa88b ("VFS: add FMODE_CAN_ODIRECT file flag")
Signed-off-by: Dave Wysochanski &lt;dwysocha@redhat.com&gt;
Signed-off-by: Anna Schumaker &lt;Anna.Schumaker@Netapp.com&gt;
</content>
</entry>
<entry>
<title>nfs: Convert to free_folio</title>
<updated>2022-05-10T03:12:53+00:00</updated>
<author>
<name>Matthew Wilcox (Oracle)</name>
<email>willy@infradead.org</email>
</author>
<published>2022-05-01T12:00:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=aa5dc8c46189779555e491d5a5ae1cc717ead774'/>
<id>urn:sha1:aa5dc8c46189779555e491d5a5ae1cc717ead774</id>
<content type='text'>
Add a wrapper that converts back from the folio to the page.  This
entire file needs to be converted to use folios, but that's a
task for a different set of patches.

Signed-off-by: Matthew Wilcox (Oracle) &lt;willy@infradead.org&gt;
</content>
</entry>
<entry>
<title>NFS: Replace readdir's use of xxhash() with hash_64()</title>
<updated>2022-04-07T20:19:47+00:00</updated>
<author>
<name>Trond Myklebust</name>
<email>trond.myklebust@hammerspace.com</email>
</author>
<published>2022-03-31T00:00:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=830f1111d90e8770fcfad8bd5628e8ae6fecec06'/>
<id>urn:sha1:830f1111d90e8770fcfad8bd5628e8ae6fecec06</id>
<content type='text'>
Both xxhash() and hash_64() appear to give similarly low collision
rates with a standard linearly increasing readdir offset. They both give
similarly higher collision rates when applied to ext4's offsets.

So switch to using the standard hash_64().

Signed-off-by: Trond Myklebust &lt;trond.myklebust@hammerspace.com&gt;
</content>
</entry>
<entry>
<title>NFSv4: fix open failure with O_ACCMODE flag</title>
<updated>2022-03-30T02:14:00+00:00</updated>
<author>
<name>ChenXiaoSong</name>
<email>chenxiaosong2@huawei.com</email>
</author>
<published>2022-03-29T11:32:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=b243874f6f9568b2daf1a00e9222cacdc15e159c'/>
<id>urn:sha1:b243874f6f9568b2daf1a00e9222cacdc15e159c</id>
<content type='text'>
open() with O_ACCMODE|O_DIRECT flags secondly will fail.

Reproducer:
  1. mount -t nfs -o vers=4.2 $server_ip:/ /mnt/
  2. fd = open("/mnt/file", O_ACCMODE|O_DIRECT|O_CREAT)
  3. close(fd)
  4. fd = open("/mnt/file", O_ACCMODE|O_DIRECT)

Server nfsd4_decode_share_access() will fail with error nfserr_bad_xdr when
client use incorrect share access mode of 0.

Fix this by using NFS4_SHARE_ACCESS_BOTH share access mode in client,
just like firstly opening.

Fixes: ce4ef7c0a8a05 ("NFS: Split out NFS v4 file operations")
Signed-off-by: ChenXiaoSong &lt;chenxiaosong2@huawei.com&gt;
Signed-off-by: Trond Myklebust &lt;trond.myklebust@hammerspace.com&gt;
</content>
</entry>
<entry>
<title>NFS: Fix revalidation of empty readdir pages</title>
<updated>2022-03-22T19:52:55+00:00</updated>
<author>
<name>Trond Myklebust</name>
<email>trond.myklebust@hammerspace.com</email>
</author>
<published>2022-03-22T13:11:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=e47a62df29a0714cc2d5129516a3618337c84554'/>
<id>urn:sha1:e47a62df29a0714cc2d5129516a3618337c84554</id>
<content type='text'>
If the page is empty, we need to check the array-&gt;last_cookie instead of
the first entry. Add a helper for the cases where we care.

Signed-off-by: Trond Myklebust &lt;trond.myklebust@hammerspace.com&gt;
</content>
</entry>
</feed>
