[PATCH] v9fs: simplify fid mapping

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 <ericvh@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Eric Van Hensbergen
2006-03-02 02:54:33 -08:00
committed by Linus Torvalds
parent 74b8054c73
commit 46f6dac259
4 changed files with 15 additions and 126 deletions

View File

@@ -1,7 +1,7 @@
/*
* V9FS FID Management
*
* Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com>
*
* 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
@@ -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;
}
@@ -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;
}
/**
@@ -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
*
*/
@@ -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;