Skip to content

Commit

Permalink
[PATCH] v9fs: simplify fid mapping
Browse files Browse the repository at this point in the history
v9fs has been plagued by an over-complicated approach trying to map Linux
dentry semantics to Plan 9 fid semantics.  Our previous approach called for
aggressive flushing of the dcache resulting in several problems (including
wierd cwd behavior when running /bin/pwd).

This patch dramatically simplifies our handling of this fid management.  Fids
will not be clunked as promptly, but the new approach is more functionally
correct.  We now clunk un-open fids only when their dentry ref_count reaches 0
(and d_delete is called).

Another simplification is we no longer seek to match fids to the process-id or
uid of the action initiator.  The uid-matching will need to be revisited when
we fix the security model.

Signed-off-by: Eric Van Hensbergen <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
ericvh authored and Linus Torvalds committed Mar 2, 2006
1 parent 74b8054 commit 46f6dac
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 126 deletions.
94 changes: 6 additions & 88 deletions fs/9p/fid.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* V9FS FID Management
*
* Copyright (C) 2005 by Eric Van Hensbergen <[email protected]>
* Copyright (C) 2005, 2006 by Eric Van Hensbergen <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -57,7 +57,6 @@ int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
}

fid->uid = current->uid;
fid->pid = current->pid;
list_add(&fid->list, fid_list);
return 0;
}
Expand Down Expand Up @@ -88,7 +87,7 @@ struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid)
new->rdir_fcall = NULL;
INIT_LIST_HEAD(&new->list);

return new;
return new;
}

/**
Expand All @@ -103,76 +102,14 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
kfree(fid);
}

/**
* v9fs_fid_walk_up - walks from the process current directory
* up to the specified dentry.
*/
static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry)
{
int fidnum, cfidnum, err;
struct v9fs_fid *cfid, *fid;
struct dentry *cde;
struct v9fs_session_info *v9ses;

v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode);
cfid = v9fs_fid_lookup(current->fs->pwd);
if (cfid == NULL) {
dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n");
return ERR_PTR(-ENOENT);
}

cfidnum = cfid->fid;
cde = current->fs->pwd;
/* TODO: take advantage of multiwalk */

fidnum = v9fs_get_idpool(&v9ses->fidpool);
if (fidnum < 0) {
dprintk(DEBUG_ERROR, "could not get a new fid num\n");
err = -ENOENT;
goto clunk_fid;
}

while (cde != dentry) {
if (cde == cde->d_parent) {
dprintk(DEBUG_ERROR, "can't find dentry\n");
err = -ENOENT;
goto clunk_fid;
}

err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL);
if (err < 0) {
dprintk(DEBUG_ERROR, "problem walking to parent\n");
goto clunk_fid;
}

cfidnum = fidnum;
cde = cde->d_parent;
}

fid = v9fs_fid_create(v9ses, fidnum);
if (fid) {
err = v9fs_fid_insert(fid, dentry);
if (err < 0) {
kfree(fid);
goto clunk_fid;
}
}

return fid;

clunk_fid:
v9fs_t_clunk(v9ses, fidnum);
return ERR_PTR(err);
}

/**
* v9fs_fid_lookup - retrieve the right fid from a particular dentry
* @dentry: dentry to look for fid in
* @type: intent of lookup (operation or traversal)
*
* search list of fids associated with a dentry for a fid with a matching
* thread id or uid. If that fails, look up the dentry's parents to see if you
* can find a matching fid.
* find a fid in the dentry
*
* TODO: only match fids that have the same uid as current user
*
*/

Expand All @@ -187,26 +124,7 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
return_fid = list_entry(fid_list->next, struct v9fs_fid, list);

if (!return_fid) {
struct dentry *par = current->fs->pwd->d_parent;
int count = 1;
while (par != NULL) {
if (par == dentry)
break;
count++;
if (par == par->d_parent) {
dprintk(DEBUG_ERROR,
"got to root without finding dentry\n");
break;
}
par = par->d_parent;
}

/* XXX - there may be some duplication we can get rid of */
if (par == dentry) {
return_fid = v9fs_fid_walk_up(dentry);
if (IS_ERR(return_fid))
return_fid = NULL;
}
dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n");
}

return return_fid;
Expand Down
1 change: 0 additions & 1 deletion fs/9p/fid.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ struct v9fs_fid {
struct v9fs_fcall *rdir_fcall;

/* management stuff */
pid_t pid; /* thread associated with this fid */
uid_t uid; /* user associated with this fid */

/* private data */
Expand Down
1 change: 1 addition & 0 deletions fs/9p/v9fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
}

if (v9ses->afid != ~0) {
dprintk(DEBUG_ERROR, "afid not equal to ~0\n");
if (v9fs_t_clunk(v9ses, v9ses->afid))
dprintk(DEBUG_ERROR, "clunk failed\n");
}
Expand Down
45 changes: 8 additions & 37 deletions fs/9p/vfs_dentry.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,47 +43,18 @@
#include "fid.h"

/**
* v9fs_dentry_validate - VFS dcache hook to validate cache
* @dentry: dentry that is being validated
* @nd: path data
* v9fs_dentry_delete - called when dentry refcount equals 0
* @dentry: dentry in question
*
* dcache really shouldn't be used for 9P2000 as at all due to
* potential attached semantics to directory traversal (walk).
*
* FUTURE: look into how to use dcache to allow multi-stage
* walks in Plan 9 & potential for better dcache operation which
* would remain valid for Plan 9 semantics. Older versions
* had validation via stat for those interested. However, since
* stat has the same approximate overhead as walk there really
* is no difference. The only improvement would be from a
* time-decay cache like NFS has and that undermines the
* synchronous nature of 9P2000.
* By returning 1 here we should remove cacheing of unused
* dentry components.
*
*/

static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd)
int v9fs_dentry_delete(struct dentry *dentry)
{
struct dentry *dc = current->fs->pwd;

dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry);
if (v9fs_fid_lookup(dentry)) {
dprintk(DEBUG_VFS, "VALID\n");
return 1;
}

while (dc != NULL) {
if (dc == dentry) {
dprintk(DEBUG_VFS, "VALID\n");
return 1;
}
if (dc == dc->d_parent)
break;

dc = dc->d_parent;
}

dprintk(DEBUG_VFS, "INVALID\n");
return 0;
dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
return 1;
}

/**
Expand Down Expand Up @@ -118,6 +89,6 @@ void v9fs_dentry_release(struct dentry *dentry)
}

struct dentry_operations v9fs_dentry_operations = {
.d_revalidate = v9fs_dentry_validate,
.d_delete = v9fs_dentry_delete,
.d_release = v9fs_dentry_release,
};

0 comments on commit 46f6dac

Please sign in to comment.