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

📄 nfs4proc.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	};	struct nfs_openargs o_arg = {		.fh             = NFS_FH(dir),		.open_flags	= flags,		.name           = name,		.server         = server,		.bitmask = server->attr_bitmask,		.claim = NFS4_OPEN_CLAIM_NULL,	};	struct nfs_openres o_res = {		.f_attr         = &f_attr,		.server         = server,	};	struct rpc_message msg = {		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN],		.rpc_argp       = &o_arg,		.rpc_resp       = &o_res,		.rpc_cred	= cred,	};	/* Protect against reboot recovery conflicts */	down_read(&clp->cl_sem);	status = -ENOMEM;	if (!(sp = nfs4_get_state_owner(server, cred))) {		dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");		goto out_err;	}	if (flags & O_EXCL) {		u32 *p = (u32 *) o_arg.u.verifier.data;		p[0] = jiffies;		p[1] = current->pid;	} else		o_arg.u.attrs = sattr;	/* Serialization for the sequence id */	down(&sp->so_sema);	o_arg.seqid = sp->so_seqid;	o_arg.id = sp->so_id;	o_arg.clientid = clp->cl_clientid,	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);	nfs4_increment_seqid(status, sp);	if (status)		goto out_err;	update_changeattr(dir, &o_res.cinfo);	if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {		status = _nfs4_proc_open_confirm(server->client, &o_res.fh,				sp, &o_res.stateid);		if (status != 0)			goto out_err;	}	if (!(f_attr.valid & NFS_ATTR_FATTR)) {		status = server->rpc_ops->getattr(server, &o_res.fh, &f_attr);		if (status < 0)			goto out_err;	}	status = -ENOMEM;	inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);	if (!inode)		goto out_err;	state = nfs4_get_open_state(inode, sp);	if (!state)		goto out_err;	memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));	spin_lock(&inode->i_lock);	if (flags & FMODE_READ)		state->nreaders++;	if (flags & FMODE_WRITE)		state->nwriters++;	state->state |= flags & (FMODE_READ|FMODE_WRITE);	spin_unlock(&inode->i_lock);	if (o_res.delegation_type != 0)		nfs_inode_set_delegation(inode, cred, &o_res);	up(&sp->so_sema);	nfs4_put_state_owner(sp);	up_read(&clp->cl_sem);	*res = state;	return 0;out_err:	if (sp != NULL) {		if (state != NULL)			nfs4_put_open_state(state);		up(&sp->so_sema);		nfs4_put_state_owner(sp);	}	/* Note: clp->cl_sem must be released before nfs4_put_open_state()! */	up_read(&clp->cl_sem);	if (inode != NULL)		iput(inode);	*res = NULL;	return status;}struct nfs4_state *nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *sattr, struct rpc_cred *cred){	struct nfs4_exception exception = { };	struct nfs4_state *res;	int status;	do {		status = _nfs4_do_open(dir, name, flags, sattr, cred, &res);		if (status == 0)			break;		/* NOTE: BAD_SEQID means the server and client disagree about the		 * book-keeping w.r.t. state-changing operations		 * (OPEN/CLOSE/LOCK/LOCKU...)		 * It is actually a sign of a bug on the client or on the server.		 *		 * If we receive a BAD_SEQID error in the particular case of		 * doing an OPEN, we assume that nfs4_increment_seqid() will		 * have unhashed the old state_owner for us, and that we can		 * therefore safely retry using a new one. We should still warn		 * the user though...		 */		if (status == -NFS4ERR_BAD_SEQID) {			printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");			exception.retry = 1;			continue;		}		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),					status, &exception));	} while (exception.retry);	return res;}static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,                struct nfs_fh *fhandle, struct iattr *sattr,                struct nfs4_state *state){        struct nfs_setattrargs  arg = {                .fh             = fhandle,                .iap            = sattr,		.server		= server,		.bitmask = server->attr_bitmask,        };        struct nfs_setattrres  res = {		.fattr		= fattr,		.server		= server,        };        struct rpc_message msg = {                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],                .rpc_argp       = &arg,                .rpc_resp       = &res,        };        fattr->valid = 0;	if (sattr->ia_valid & ATTR_SIZE)		nfs4_copy_stateid(&arg.stateid, state, NULL);	else		memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));	return rpc_call_sync(server->client, &msg, 0);}int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,                struct nfs_fh *fhandle, struct iattr *sattr,                struct nfs4_state *state){	struct nfs4_exception exception = { };	int err;	do {		err = nfs4_handle_exception(server,				_nfs4_do_setattr(server, fattr, fhandle, sattr,					state),				&exception);	} while (exception.retry);	return err;}/*  * It is possible for data to be read/written from a mem-mapped file  * after the sys_close call (which hits the vfs layer as a flush). * This means that we can't safely call nfsv4 close on a file until  * the inode is cleared. This in turn means that we are not good * NFSv4 citizens - we do not indicate to the server to update the file's  * share state even when we are done with one of the three share  * stateid's in the inode. * * NOTE: Caller must be holding the sp->so_owner semaphore! */static int _nfs4_do_close(struct inode *inode, struct nfs4_state *state) {	struct nfs4_state_owner *sp = state->owner;	int status = 0;	struct nfs_closeargs arg = {		.fh		= NFS_FH(inode),	};	struct nfs_closeres res;	struct rpc_message msg = {		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_CLOSE],		.rpc_argp	= &arg,		.rpc_resp	= &res,	};	if (test_bit(NFS_DELEGATED_STATE, &state->flags))		return 0;	memcpy(&arg.stateid, &state->stateid, sizeof(arg.stateid));	/* Serialization for the sequence id */	arg.seqid = sp->so_seqid,	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, RPC_TASK_NOINTR);        /* hmm. we are done with the inode, and in the process of freeing	 * the state_owner. we keep this around to process errors	 */	nfs4_increment_seqid(status, sp);	if (!status)		memcpy(&state->stateid, &res.stateid, sizeof(state->stateid));	return status;}int nfs4_do_close(struct inode *inode, struct nfs4_state *state) {	struct nfs_server *server = NFS_SERVER(state->inode);	struct nfs4_exception exception = { };	int err;	do {		err = _nfs4_do_close(inode, state);		switch (err) {			case -NFS4ERR_STALE_STATEID:			case -NFS4ERR_EXPIRED:				nfs4_schedule_state_recovery(server->nfs4_state);				err = 0;			default:				state->state = 0;		}		err = nfs4_handle_exception(server, err, &exception);	} while (exception.retry);	return err;}static int _nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode) {	struct nfs4_state_owner *sp = state->owner;	int status = 0;	struct nfs_closeargs arg = {		.fh		= NFS_FH(inode),		.seqid		= sp->so_seqid,		.open_flags	= mode,	};	struct nfs_closeres res;	struct rpc_message msg = {		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE],		.rpc_argp	= &arg,		.rpc_resp	= &res,	};	if (test_bit(NFS_DELEGATED_STATE, &state->flags))		return 0;	memcpy(&arg.stateid, &state->stateid, sizeof(arg.stateid));	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, RPC_TASK_NOINTR);	nfs4_increment_seqid(status, sp);	if (!status)		memcpy(&state->stateid, &res.stateid, sizeof(state->stateid));	return status;}int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode) {	struct nfs_server *server = NFS_SERVER(state->inode);	struct nfs4_exception exception = { };	int err;	do {		err = _nfs4_do_downgrade(inode, state, mode);		switch (err) {			case -NFS4ERR_STALE_STATEID:			case -NFS4ERR_EXPIRED:				nfs4_schedule_state_recovery(server->nfs4_state);				err = 0;			default:				state->state = mode;		}		err = nfs4_handle_exception(server, err, &exception);	} while (exception.retry);	return err;}struct inode *nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd){	struct iattr attr;	struct rpc_cred *cred;	struct nfs4_state *state;	if (nd->flags & LOOKUP_CREATE) {		attr.ia_mode = nd->intent.open.create_mode;		attr.ia_valid = ATTR_MODE;		if (!IS_POSIXACL(dir))			attr.ia_mode &= ~current->fs->umask;	} else {		attr.ia_valid = 0;		BUG_ON(nd->intent.open.flags & O_CREAT);	}	cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);	state = nfs4_do_open(dir, &dentry->d_name, nd->intent.open.flags, &attr, cred);	put_rpccred(cred);	if (IS_ERR(state))		return (struct inode *)state;	return state->inode;}intnfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags){	struct rpc_cred *cred;	struct nfs4_state *state;	struct inode *inode;	cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);	state = nfs4_open_delegated(dentry->d_inode, openflags, cred);	if (IS_ERR(state))		state = nfs4_do_open(dir, &dentry->d_name, openflags, NULL, cred);	put_rpccred(cred);	if (state == ERR_PTR(-ENOENT) && dentry->d_inode == 0)		return 1;	if (IS_ERR(state))		return 0;	inode = state->inode;	if (inode == dentry->d_inode) {		iput(inode);		return 1;	}	d_drop(dentry);	nfs4_close_state(state, openflags);	iput(inode);	return 0;}static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle){	struct nfs4_server_caps_res res = {};	struct rpc_message msg = {		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],		.rpc_argp = fhandle,		.rpc_resp = &res,	};	int status;	status = rpc_call_sync(server->client, &msg, 0);	if (status == 0) {		memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));		if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)			server->caps |= NFS_CAP_ACLS;		if (res.has_links != 0)			server->caps |= NFS_CAP_HARDLINKS;		if (res.has_symlinks != 0)			server->caps |= NFS_CAP_SYMLINKS;		server->acl_bitmask = res.acl_bitmask;	}	return status;}static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle){	struct nfs4_exception exception = { };	int err;	do {		err = nfs4_handle_exception(server,				_nfs4_server_capabilities(server, fhandle),				&exception);	} while (exception.retry);	return err;}static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,		struct nfs_fsinfo *info){	struct nfs_fattr *	fattr = info->fattr;	struct nfs4_lookup_root_arg args = {		.bitmask = nfs4_fattr_bitmap,	};	struct nfs4_lookup_res res = {		.server = server,		.fattr = fattr,		.fh = fhandle,	};	struct rpc_message msg = {		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP_ROOT],		.rpc_argp = &args,		.rpc_resp = &res,	};	fattr->valid = 0;	return rpc_call_sync(server->client, &msg, 0);}static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,		struct nfs_fsinfo *info){	struct nfs4_exception exception = { };	int err;	do {		err = nfs4_handle_exception(server,				_nfs4_lookup_root(server, fhandle, info),				&exception);	} while (exception.retry);	return err;}static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,		struct nfs_fsinfo *info){	struct nfs_fattr *	fattr = info->fattr;	unsigned char *		p;	struct qstr		q;	struct nfs4_lookup_arg args = {		.dir_fh = fhandle,		.name = &q,		.bitmask = nfs4_fattr_bitmap,	};	struct nfs4_lookup_res res = {		.server = server,		.fattr = fattr,		.fh = fhandle,	};	struct rpc_message msg = {		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],		.rpc_argp = &args,		.rpc_resp = &res,	};	int status;	/*	 * Now we do a separate LOOKUP for each component of the mount path.	 * The LOOKUPs are done separately so that we can conveniently	 * catch an ERR_WRONGSEC if it occurs along the way...	 */	status = nfs4_lookup_root(server, fhandle, info);	if (status)		goto out;	p = server->mnt_path;	for (;;) {		struct nfs4_exception exception = { };		while (*p == '/')			p++;		if (!*p)			break;		q.name = p;		while (*p && (*p != '/'))			p++;		q.len = p - q.name;		do {			fattr->valid = 0;			status = nfs4_handle_exception(server,					rpc_call_sync(server->client, &msg, 0),					&exception);		} while (exception.retry);		if (status == 0)			continue;		if (status == -ENOENT) {			printk(KERN_NOTICE "NFS: mount path %s does not exist!\n", server->mnt_path);			printk(KERN_NOTICE "NFS: suggestion: try mounting '/' instead.\n");		}		break;	}	if (status == 0)		status = nfs4_server_capabilities(server, fhandle);	if (status == 0)		status = nfs4_do_fsinfo(server, fhandle, info);out:	return status;}static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr){	struct nfs4_getattr_arg args = {		.fh = fhandle,		.bitmask = server->attr_bitmask,	};	struct nfs4_getattr_res res = {		.fattr = fattr,		.server = server,	};	struct rpc_message msg = {		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR],		.rpc_argp = &args,		.rpc_resp = &res,	};		fattr->valid = 0;	return rpc_call_sync(server->client, &msg, 0);}

⌨️ 快捷键说明

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