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

📄 nfs3proc.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/nfs/nfs3proc.c * *  Client-side NFSv3 procedures stubs. * *  Copyright (C) 1997, Olaf Kirch */#include <linux/mm.h>#include <linux/utsname.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/sunrpc/clnt.h>#include <linux/nfs.h>#include <linux/nfs3.h>#include <linux/nfs_fs.h>#include <linux/nfs_page.h>#include <linux/lockd/bind.h>#include <linux/smp_lock.h>#define NFSDBG_FACILITY		NFSDBG_PROCextern struct rpc_procinfo nfs3_procedures[];/* A wrapper to handle the EJUKEBOX error message */static intnfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags){	sigset_t oldset;	int res;	rpc_clnt_sigmask(clnt, &oldset);	do {		res = rpc_call_sync(clnt, msg, flags);		if (res != -EJUKEBOX)			break;		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(NFS_JUKEBOX_RETRY_TIME);		res = -ERESTARTSYS;	} while (!signalled());	rpc_clnt_sigunmask(clnt, &oldset);	return res;}static inline intnfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags){	struct rpc_message msg = {		.rpc_proc	= &nfs3_procedures[proc],		.rpc_argp	= argp,		.rpc_resp	= resp,	};	return nfs3_rpc_wrapper(clnt, &msg, flags);}#define rpc_call(clnt, proc, argp, resp, flags) \		nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags)#define rpc_call_sync(clnt, msg, flags) \		nfs3_rpc_wrapper(clnt, msg, flags)static intnfs3_async_handle_jukebox(struct rpc_task *task){	if (task->tk_status != -EJUKEBOX)		return 0;	task->tk_status = 0;	rpc_restart_call(task);	rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);	return 1;}/* * Bare-bones access to getattr: this is for nfs_read_super. */static intnfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,		   struct nfs_fsinfo *info){	int	status;	dprintk("%s: call  fsinfo\n", __FUNCTION__);	info->fattr->valid = 0;	status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);	dprintk("%s: reply fsinfo %d\n", __FUNCTION__, status);	if (!(info->fattr->valid & NFS_ATTR_FATTR)) {		status = rpc_call(server->client_sys, NFS3PROC_GETATTR, fhandle, info->fattr, 0);		dprintk("%s: reply getattr %d\n", __FUNCTION__, status);	}	return status;}/* * One function for each procedure in the NFS protocol. */static intnfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,		struct nfs_fattr *fattr){	int	status;	dprintk("NFS call  getattr\n");	fattr->valid = 0;	status = rpc_call(server->client, NFS3PROC_GETATTR,			  fhandle, fattr, 0);	dprintk("NFS reply getattr\n");	return status;}static intnfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,			struct iattr *sattr){	struct inode *inode = dentry->d_inode;	struct nfs3_sattrargs	arg = {		.fh		= NFS_FH(inode),		.sattr		= sattr,	};	int	status;	dprintk("NFS call  setattr\n");	fattr->valid = 0;	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);	dprintk("NFS reply setattr\n");	return status;}static intnfs3_proc_lookup(struct inode *dir, struct qstr *name,		 struct nfs_fh *fhandle, struct nfs_fattr *fattr){	struct nfs_fattr	dir_attr;	struct nfs3_diropargs	arg = {		.fh		= NFS_FH(dir),		.name		= name->name,		.len		= name->len	};	struct nfs3_diropres	res = {		.dir_attr	= &dir_attr,		.fh		= fhandle,		.fattr		= fattr	};	int			status;	dprintk("NFS call  lookup %s\n", name->name);	dir_attr.valid = 0;	fattr->valid = 0;	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);	if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))		status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,			 fhandle, fattr, 0);	dprintk("NFS reply lookup: %d\n", status);	if (status >= 0)		status = nfs_refresh_inode(dir, &dir_attr);	return status;}static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry){	struct nfs_fattr	fattr;	struct nfs3_accessargs	arg = {		.fh		= NFS_FH(inode),	};	struct nfs3_accessres	res = {		.fattr		= &fattr,	};	struct rpc_message msg = {		.rpc_proc	= &nfs3_procedures[NFS3PROC_ACCESS],		.rpc_argp	= &arg,		.rpc_resp	= &res,		.rpc_cred	= entry->cred	};	int mode = entry->mask;	int status;	dprintk("NFS call  access\n");	fattr.valid = 0;	if (mode & MAY_READ)		arg.access |= NFS3_ACCESS_READ;	if (S_ISDIR(inode->i_mode)) {		if (mode & MAY_WRITE)			arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;		if (mode & MAY_EXEC)			arg.access |= NFS3_ACCESS_LOOKUP;	} else {		if (mode & MAY_WRITE)			arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND;		if (mode & MAY_EXEC)			arg.access |= NFS3_ACCESS_EXECUTE;	}	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);	nfs_refresh_inode(inode, &fattr);	if (status == 0) {		entry->mask = 0;		if (res.access & NFS3_ACCESS_READ)			entry->mask |= MAY_READ;		if (res.access & (NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE))			entry->mask |= MAY_WRITE;		if (res.access & (NFS3_ACCESS_LOOKUP|NFS3_ACCESS_EXECUTE))			entry->mask |= MAY_EXEC;	}	dprintk("NFS reply access, status = %d\n", status);	return status;}static int nfs3_proc_readlink(struct inode *inode, struct page *page,		unsigned int pgbase, unsigned int pglen){	struct nfs_fattr	fattr;	struct nfs3_readlinkargs args = {		.fh		= NFS_FH(inode),		.pgbase		= pgbase,		.pglen		= pglen,		.pages		= &page	};	int			status;	dprintk("NFS call  readlink\n");	fattr.valid = 0;	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,			  &args, &fattr, 0);	nfs_refresh_inode(inode, &fattr);	dprintk("NFS reply readlink: %d\n", status);	return status;}static int nfs3_proc_read(struct nfs_read_data *rdata){	int			flags = rdata->flags;	struct inode *		inode = rdata->inode;	struct nfs_fattr *	fattr = rdata->res.fattr;	struct rpc_message	msg = {		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],		.rpc_argp	= &rdata->args,		.rpc_resp	= &rdata->res,		.rpc_cred	= rdata->cred,	};	int			status;	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,			(long long) rdata->args.offset);	fattr->valid = 0;	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);	if (status >= 0)		nfs_refresh_inode(inode, fattr);	dprintk("NFS reply read: %d\n", status);	return status;}static int nfs3_proc_write(struct nfs_write_data *wdata){	int			rpcflags = wdata->flags;	struct inode *		inode = wdata->inode;	struct nfs_fattr *	fattr = wdata->res.fattr;	struct rpc_message	msg = {		.rpc_proc	= &nfs3_procedures[NFS3PROC_WRITE],		.rpc_argp	= &wdata->args,		.rpc_resp	= &wdata->res,		.rpc_cred	= wdata->cred,	};	int			status;	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,			(long long) wdata->args.offset);	fattr->valid = 0;	status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);	if (status >= 0)		nfs_refresh_inode(inode, fattr);	dprintk("NFS reply write: %d\n", status);	return status < 0? status : wdata->res.count;}static int nfs3_proc_commit(struct nfs_write_data *cdata){	struct inode *		inode = cdata->inode;	struct nfs_fattr *	fattr = cdata->res.fattr;	struct rpc_message	msg = {		.rpc_proc	= &nfs3_procedures[NFS3PROC_COMMIT],		.rpc_argp	= &cdata->args,		.rpc_resp	= &cdata->res,		.rpc_cred	= cdata->cred,	};	int			status;	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,			(long long) cdata->args.offset);	fattr->valid = 0;	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);	if (status >= 0)		nfs_refresh_inode(inode, fattr);	dprintk("NFS reply commit: %d\n", status);	return status;}/* * Create a regular file. * For now, we don't implement O_EXCL. */static struct inode *nfs3_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,		 int flags){	struct nfs_fh		fhandle;	struct nfs_fattr	fattr;	struct nfs_fattr	dir_attr;	struct nfs3_createargs	arg = {		.fh		= NFS_FH(dir),		.name		= name->name,		.len		= name->len,		.sattr		= sattr,	};	struct nfs3_diropres	res = {		.dir_attr	= &dir_attr,		.fh		= &fhandle,		.fattr		= &fattr	};	int			status;	dprintk("NFS call  create %s\n", name->name);	arg.createmode = NFS3_CREATE_UNCHECKED;	if (flags & O_EXCL) {		arg.createmode  = NFS3_CREATE_EXCLUSIVE;		arg.verifier[0] = jiffies;		arg.verifier[1] = current->pid;	}again:	dir_attr.valid = 0;	fattr.valid = 0;	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);	nfs_refresh_inode(dir, &dir_attr);	/* If the server doesn't support the exclusive creation semantics,	 * try again with simple 'guarded' mode. */	if (status == NFSERR_NOTSUPP) {		switch (arg.createmode) {			case NFS3_CREATE_EXCLUSIVE:				arg.createmode = NFS3_CREATE_GUARDED;				break;			case NFS3_CREATE_GUARDED:				arg.createmode = NFS3_CREATE_UNCHECKED;				break;			case NFS3_CREATE_UNCHECKED:				goto exit;		}		goto again;	}exit:	dprintk("NFS reply create: %d\n", status);	if (status != 0)		goto out;	if (fhandle.size == 0 || !(fattr.valid & NFS_ATTR_FATTR)) {		status = nfs3_proc_lookup(dir, name, &fhandle, &fattr);		if (status != 0)			goto out;	}	/* When we created the file with exclusive semantics, make	 * sure we set the attributes afterwards. */	if (arg.createmode == NFS3_CREATE_EXCLUSIVE) {		struct nfs3_sattrargs	arg = {			.fh		= &fhandle,			.sattr		= sattr,		};		dprintk("NFS call  setattr (post-create)\n");		if (!(sattr->ia_valid & ATTR_ATIME_SET))			sattr->ia_valid |= ATTR_ATIME;		if (!(sattr->ia_valid & ATTR_MTIME_SET))			sattr->ia_valid |= ATTR_MTIME;		/* Note: we could use a guarded setattr here, but I'm		 * not sure this buys us anything (and I'd have		 * to revamp the NFSv3 XDR code) */		fattr.valid = 0;		status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,						&arg, &fattr, 0);		dprintk("NFS reply setattr (post-create): %d\n", status);	}	if (status == 0) {		struct inode *inode;		inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);		if (inode)			return inode;		status = -ENOMEM;	}out:	return ERR_PTR(status);}static intnfs3_proc_remove(struct inode *dir, struct qstr *name){	struct nfs_fattr	dir_attr;	struct nfs3_diropargs	arg = {		.fh		= NFS_FH(dir),		.name		= name->name,		.len		= name->len	};	struct rpc_message	msg = {		.rpc_proc	= &nfs3_procedures[NFS3PROC_REMOVE],		.rpc_argp	= &arg,		.rpc_resp	= &dir_attr,	};	int			status;	dprintk("NFS call  remove %s\n", name->name);	dir_attr.valid = 0;	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);	nfs_refresh_inode(dir, &dir_attr);	dprintk("NFS reply remove: %d\n", status);	return status;}static intnfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name){	struct unlinkxdr {		struct nfs3_diropargs arg;		struct nfs_fattr res;	} *ptr;	ptr = (struct unlinkxdr *)kmalloc(sizeof(*ptr), GFP_KERNEL);	if (!ptr)		return -ENOMEM;	ptr->arg.fh = NFS_FH(dir->d_inode);	ptr->arg.name = name->name;	ptr->arg.len = name->len;	ptr->res.valid = 0;	msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];	msg->rpc_argp = &ptr->arg;	msg->rpc_resp = &ptr->res;	return 0;

⌨️ 快捷键说明

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