⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fid.c

📁 linux 内核源代码
💻 C
字号:
/* * V9FS FID Management * *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> *  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 version 2 *  as published by the Free Software Foundation. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to: *  Free Software Foundation *  51 Franklin Street, Fifth Floor *  Boston, MA  02111-1301  USA * */#include <linux/module.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/idr.h>#include <asm/semaphore.h>#include <net/9p/9p.h>#include <net/9p/client.h>#include "v9fs.h"#include "v9fs_vfs.h"#include "fid.h"/** * v9fs_fid_add - add a fid to a dentry * @dentry: dentry that the fid is being added to * @fid: fid to add * */int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid){	struct v9fs_dentry *dent;	P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n",					fid->fid, dentry->d_iname);	dent = dentry->d_fsdata;	if (!dent) {		dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL);		if (!dent)			return -ENOMEM;		spin_lock_init(&dent->lock);		INIT_LIST_HEAD(&dent->fidlist);		dentry->d_fsdata = dent;	}	spin_lock(&dent->lock);	list_add(&fid->dlist, &dent->fidlist);	spin_unlock(&dent->lock);	return 0;}/** * v9fs_fid_find - retrieve a fid that belongs to the specified uid * @dentry: dentry to look for fid in * @uid: return fid that belongs to the specified user * @any: if non-zero, return any fid associated with the dentry * */static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any){	struct v9fs_dentry *dent;	struct p9_fid *fid, *ret;	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n",		dentry->d_iname, dentry, uid, any);	dent = (struct v9fs_dentry *) dentry->d_fsdata;	ret = NULL;	if (dent) {		spin_lock(&dent->lock);		list_for_each_entry(fid, &dent->fidlist, dlist) {			if (any || fid->uid == uid) {				ret = fid;				break;			}		}		spin_unlock(&dent->lock);	}	return ret;}/** * v9fs_fid_lookup - lookup for a fid, try to walk if not found * @dentry: dentry to look for fid in * * Look for a fid in the specified dentry for the current user. * If no fid is found, try to create one walking from a fid from the parent * dentry (if it has one), or the root dentry. If the user haven't accessed * the fs yet, attach now and walk from the root. */struct p9_fid *v9fs_fid_lookup(struct dentry *dentry){	int i, n, l, clone, any, access;	u32 uid;	struct p9_fid *fid;	struct dentry *d, *ds;	struct v9fs_session_info *v9ses;	char **wnames, *uname;	v9ses = v9fs_inode2v9ses(dentry->d_inode);	access = v9ses->flags & V9FS_ACCESS_MASK;	switch (access) {	case V9FS_ACCESS_SINGLE:	case V9FS_ACCESS_USER:		uid = current->fsuid;		any = 0;		break;	case V9FS_ACCESS_ANY:		uid = v9ses->uid;		any = 1;		break;	default:		uid = ~0;		any = 0;		break;	}	fid = v9fs_fid_find(dentry, uid, any);	if (fid)		return fid;	ds = dentry->d_parent;	fid = v9fs_fid_find(ds, uid, any);	if (!fid) { /* walk from the root */		n = 0;		for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent)			n++;		fid = v9fs_fid_find(ds, uid, any);		if (!fid) { /* the user is not attached to the fs yet */			if (access == V9FS_ACCESS_SINGLE)				return ERR_PTR(-EPERM);			if (v9fs_extended(v9ses))				uname = NULL;			else				uname = v9ses->uname;			fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,				v9ses->aname);			if (IS_ERR(fid))				return fid;			v9fs_fid_add(ds, fid);		}	} else /* walk from the parent */		n = 1;	if (ds == dentry)		return fid;	wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL);	if (!wnames)		return ERR_PTR(-ENOMEM);	for (d = dentry, i = n; i >= 0; i--, d = d->d_parent)		wnames[i] = (char *) d->d_name.name;	clone = 1;	i = 0;	while (i < n) {		l = min(n - i, P9_MAXWELEM);		fid = p9_client_walk(fid, l, &wnames[i], clone);		if (!fid) {			kfree(wnames);			return fid;		}		i += l;		clone = 0;	}	kfree(wnames);	v9fs_fid_add(dentry, fid);	return fid;}struct p9_fid *v9fs_fid_clone(struct dentry *dentry){	struct p9_fid *fid, *ret;	fid = v9fs_fid_lookup(dentry);	if (IS_ERR(fid))		return fid;	ret = p9_client_walk(fid, 0, NULL, 1);	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -