mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 10:45:49 +00:00
jfs: fix readdir cookie incompatibility with NFSv4
commit 44512449c0
upstream.
NFSv4 reserves readdir cookie values 0-2 for special entries (. and ..),
but jfs allows a value of 2 for a non-special entry. This incompatibility
can result in the nfs client reporting a readdir loop.
This patch doesn't change the value stored internally, but adds one to
the value exposed to the iterate method.
Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
[bwh: Backported to 3.2:
- Adjust context
- s/ctx->pos/filp->f_pos/]
Tested-by: Christian Kujau <lists@nerdbynature.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
cc540ceece
commit
59fb9f6b1f
@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
|
||||
dir_index = (u32) filp->f_pos;
|
||||
|
||||
/*
|
||||
* NFSv4 reserves cookies 1 and 2 for . and .. so we add
|
||||
* the value we return to the vfs is one greater than the
|
||||
* one we use internally.
|
||||
*/
|
||||
if (dir_index)
|
||||
dir_index--;
|
||||
|
||||
if (dir_index > 1) {
|
||||
struct dir_table_slot dirtab_slot;
|
||||
|
||||
@ -3086,7 +3094,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
if (p->header.flag & BT_INTERNAL) {
|
||||
jfs_err("jfs_readdir: bad index table");
|
||||
DT_PUTPAGE(mp);
|
||||
filp->f_pos = -1;
|
||||
filp->f_pos = DIREND;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@ -3094,7 +3102,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
/*
|
||||
* self "."
|
||||
*/
|
||||
filp->f_pos = 0;
|
||||
filp->f_pos = 1;
|
||||
if (filldir(dirent, ".", 1, 0, ip->i_ino,
|
||||
DT_DIR))
|
||||
return 0;
|
||||
@ -3102,7 +3110,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
/*
|
||||
* parent ".."
|
||||
*/
|
||||
filp->f_pos = 1;
|
||||
filp->f_pos = 2;
|
||||
if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR))
|
||||
return 0;
|
||||
|
||||
@ -3123,24 +3131,25 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
/*
|
||||
* Legacy filesystem - OS/2 & Linux JFS < 0.3.6
|
||||
*
|
||||
* pn = index = 0: First entry "."
|
||||
* pn = 0; index = 1: Second entry ".."
|
||||
* pn = 0; index = 1: First entry "."
|
||||
* pn = 0; index = 2: Second entry ".."
|
||||
* pn > 0: Real entries, pn=1 -> leftmost page
|
||||
* pn = index = -1: No more entries
|
||||
*/
|
||||
dtpos = filp->f_pos;
|
||||
if (dtpos == 0) {
|
||||
if (dtpos < 2) {
|
||||
/* build "." entry */
|
||||
|
||||
filp->f_pos = 1;
|
||||
if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino,
|
||||
DT_DIR))
|
||||
return 0;
|
||||
dtoffset->index = 1;
|
||||
dtoffset->index = 2;
|
||||
filp->f_pos = dtpos;
|
||||
}
|
||||
|
||||
if (dtoffset->pn == 0) {
|
||||
if (dtoffset->index == 1) {
|
||||
if (dtoffset->index == 2) {
|
||||
/* build ".." entry */
|
||||
|
||||
if (filldir(dirent, "..", 2, filp->f_pos,
|
||||
@ -3233,6 +3242,12 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
}
|
||||
jfs_dirent->position = unique_pos++;
|
||||
}
|
||||
/*
|
||||
* We add 1 to the index because we may
|
||||
* use a value of 2 internally, and NFSv4
|
||||
* doesn't like that.
|
||||
*/
|
||||
jfs_dirent->position++;
|
||||
} else {
|
||||
jfs_dirent->position = dtpos;
|
||||
len = min(d_namleft, DTLHDRDATALEN_LEGACY);
|
||||
|
Loading…
Reference in New Issue
Block a user