@@ -43,6 +43,8 @@ int iterate_dir(struct file *file, struct dir_context *ctx)
struct inode *inode = file_inode(file);
bool shared = false;
int res = -ENOTDIR;
+ bool nowait;
+
if (file->f_op->iterate_shared)
shared = true;
else if (!file->f_op->iterate)
@@ -52,16 +54,22 @@ int iterate_dir(struct file *file, struct dir_context *ctx)
if (res)
goto out;
- if (shared)
- res = down_read_killable(&inode->i_rwsem);
- else
- res = down_write_killable(&inode->i_rwsem);
- if (res)
+ nowait = ctx->flags & DIR_CONTEXT_F_NOWAIT;
+ if (nowait) {
+ res = shared ? down_read_trylock(&inode->i_rwsem) :
+ down_write_trylock(&inode->i_rwsem);
+ if (!res)
+ res = -EAGAIN;
+ } else {
+ res = shared ? down_read_killable(&inode->i_rwsem) :
+ down_write_killable(&inode->i_rwsem);
+ }
+ if (res < 0)
goto out;
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
- res = file_accessed(file, ctx->flags & DIR_CONTEXT_F_NOWAIT);
+ res = file_accessed(file, nowait);
if (res == -EAGAIN)
goto out_unlock;