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

📄 nfs4state.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	return NULL;}static inline intnfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp){	return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode;}static intSTALE_STATEID(stateid_t *stateid){	if (stateid->si_boot == boot_time)		return 0;	dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",		stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,		stateid->si_generation);	return 1;}static inline intaccess_permit_read(unsigned long access_bmap){	return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||		test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap) ||		test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap);}static inline intaccess_permit_write(unsigned long access_bmap){	return test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap) ||		test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);}static__be32 nfs4_check_openmode(struct nfs4_stateid *stp, int flags){        __be32 status = nfserr_openmode;	if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap)))                goto out;	if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap)))                goto out;	status = nfs_ok;out:	return status;}static inline __be32check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags){	/* Trying to call delegreturn with a special stateid? Yuch: */	if (!(flags & (RD_STATE | WR_STATE)))		return nfserr_bad_stateid;	else if (ONE_STATEID(stateid) && (flags & RD_STATE))		return nfs_ok;	else if (nfs4_in_grace()) {		/* Answer in remaining cases depends on existance of		 * conflicting state; so we must wait out the grace period. */		return nfserr_grace;	} else if (flags & WR_STATE)		return nfs4_share_conflict(current_fh,				NFS4_SHARE_DENY_WRITE);	else /* (flags & RD_STATE) && ZERO_STATEID(stateid) */		return nfs4_share_conflict(current_fh,				NFS4_SHARE_DENY_READ);}/* * Allow READ/WRITE during grace period on recovered state only for files * that are not able to provide mandatory locking. */static inline intio_during_grace_disallowed(struct inode *inode, int flags){	return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))		&& mandatory_lock(inode);}/** Checks for stateid operations*/__be32nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct file **filpp){	struct nfs4_stateid *stp = NULL;	struct nfs4_delegation *dp = NULL;	stateid_t *stidp;	struct inode *ino = current_fh->fh_dentry->d_inode;	__be32 status;	dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",		stateid->si_boot, stateid->si_stateownerid, 		stateid->si_fileid, stateid->si_generation); 	if (filpp)		*filpp = NULL;	if (io_during_grace_disallowed(ino, flags))		return nfserr_grace;	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))		return check_special_stateids(current_fh, stateid, flags);	/* STALE STATEID */	status = nfserr_stale_stateid;	if (STALE_STATEID(stateid)) 		goto out;	/* BAD STATEID */	status = nfserr_bad_stateid;	if (!stateid->si_fileid) { /* delegation stateid */		if(!(dp = find_delegation_stateid(ino, stateid))) {			dprintk("NFSD: delegation stateid not found\n");			goto out;		}		stidp = &dp->dl_stateid;	} else { /* open or lock stateid */		if (!(stp = find_stateid(stateid, flags))) {			dprintk("NFSD: open or lock stateid not found\n");			goto out;		}		if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))			goto out;		if (!stp->st_stateowner->so_confirmed)			goto out;		stidp = &stp->st_stateid;	}	if (stateid->si_generation > stidp->si_generation)		goto out;	/* OLD STATEID */	status = nfserr_old_stateid;	if (stateid->si_generation < stidp->si_generation)		goto out;	if (stp) {		if ((status = nfs4_check_openmode(stp,flags)))			goto out;		renew_client(stp->st_stateowner->so_client);		if (filpp)			*filpp = stp->st_vfs_file;	} else if (dp) {		if ((status = nfs4_check_delegmode(dp, flags)))			goto out;		renew_client(dp->dl_client);		if (flags & DELEG_RET)			unhash_delegation(dp);		if (filpp)			*filpp = dp->dl_vfs_file;	}	status = nfs_ok;out:	return status;}static inline intsetlkflg (int type){	return (type == NFS4_READW_LT || type == NFS4_READ_LT) ?		RD_STATE : WR_STATE;}/*  * Checks for sequence id mutating operations.  */static __be32nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock){	struct nfs4_stateid *stp;	struct nfs4_stateowner *sop;	dprintk("NFSD: preprocess_seqid_op: seqid=%d " 			"stateid = (%08x/%08x/%08x/%08x)\n", seqid,		stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,		stateid->si_generation);	*stpp = NULL;	*sopp = NULL;	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {		dprintk("NFSD: preprocess_seqid_op: magic stateid!\n");		return nfserr_bad_stateid;	}	if (STALE_STATEID(stateid))		return nfserr_stale_stateid;	/*	* We return BAD_STATEID if filehandle doesn't match stateid, 	* the confirmed flag is incorrecly set, or the generation 	* number is incorrect.  	*/	stp = find_stateid(stateid, flags);	if (stp == NULL) {		/*		 * Also, we should make sure this isn't just the result of		 * a replayed close:		 */		sop = search_close_lru(stateid->si_stateownerid, flags);		if (sop == NULL)			return nfserr_bad_stateid;		*sopp = sop;		goto check_replay;	}	if (lock) {		struct nfs4_stateowner *sop = stp->st_stateowner;		clientid_t *lockclid = &lock->v.new.clientid;		struct nfs4_client *clp = sop->so_client;		int lkflg = 0;		__be32 status;		lkflg = setlkflg(lock->lk_type);		if (lock->lk_is_new) {			if (!sop->so_is_open_owner)				return nfserr_bad_stateid;			if (!same_clid(&clp->cl_clientid, lockclid))			       return nfserr_bad_stateid;			/* stp is the open stateid */			status = nfs4_check_openmode(stp, lkflg);			if (status)				return status;		} else {			/* stp is the lock stateid */			status = nfs4_check_openmode(stp->st_openstp, lkflg);			if (status)				return status;               }	}	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {		dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");		return nfserr_bad_stateid;	}	*stpp = stp;	*sopp = sop = stp->st_stateowner;	/*	*  We now validate the seqid and stateid generation numbers.	*  For the moment, we ignore the possibility of 	*  generation number wraparound.	*/	if (seqid != sop->so_seqid)		goto check_replay;	if (sop->so_confirmed && flags & CONFIRM) {		dprintk("NFSD: preprocess_seqid_op: expected"				" unconfirmed stateowner!\n");		return nfserr_bad_stateid;	}	if (!sop->so_confirmed && !(flags & CONFIRM)) {		dprintk("NFSD: preprocess_seqid_op: stateowner not"				" confirmed yet!\n");		return nfserr_bad_stateid;	}	if (stateid->si_generation > stp->st_stateid.si_generation) {		dprintk("NFSD: preprocess_seqid_op: future stateid?!\n");		return nfserr_bad_stateid;	}	if (stateid->si_generation < stp->st_stateid.si_generation) {		dprintk("NFSD: preprocess_seqid_op: old stateid!\n");		return nfserr_old_stateid;	}	renew_client(sop->so_client);	return nfs_ok;check_replay:	if (seqid == sop->so_seqid - 1) {		dprintk("NFSD: preprocess_seqid_op: retransmission?\n");		/* indicate replay to calling function */		return nfserr_replay_me;	}	dprintk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n",			sop->so_seqid, seqid);	*sopp = NULL;	return nfserr_bad_seqid;}__be32nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,		   struct nfsd4_open_confirm *oc){	__be32 status;	struct nfs4_stateowner *sop;	struct nfs4_stateid *stp;	dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",			(int)cstate->current_fh.fh_dentry->d_name.len,			cstate->current_fh.fh_dentry->d_name.name);	status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);	if (status)		return status;	nfs4_lock_state();	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,					oc->oc_seqid, &oc->oc_req_stateid,					CHECK_FH | CONFIRM | OPEN_STATE,					&oc->oc_stateowner, &stp, NULL)))		goto out; 	sop = oc->oc_stateowner;	sop->so_confirmed = 1;	update_stateid(&stp->st_stateid);	memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t));	dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d " 		"stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid,		         stp->st_stateid.si_boot,		         stp->st_stateid.si_stateownerid,		         stp->st_stateid.si_fileid,		         stp->st_stateid.si_generation);	nfsd4_create_clid_dir(sop->so_client);out:	if (oc->oc_stateowner) {		nfs4_get_stateowner(oc->oc_stateowner);		cstate->replay_owner = oc->oc_stateowner;	}	nfs4_unlock_state();	return status;}/* * unset all bits in union bitmap (bmap) that * do not exist in share (from successful OPEN_DOWNGRADE) */static voidreset_union_bmap_access(unsigned long access, unsigned long *bmap){	int i;	for (i = 1; i < 4; i++) {		if ((i & access) != i)			__clear_bit(i, bmap);	}}static voidreset_union_bmap_deny(unsigned long deny, unsigned long *bmap){	int i;	for (i = 0; i < 4; i++) {		if ((i & deny) != i)			__clear_bit(i, bmap);	}}__be32nfsd4_open_downgrade(struct svc_rqst *rqstp,		     struct nfsd4_compound_state *cstate,		     struct nfsd4_open_downgrade *od){	__be32 status;	struct nfs4_stateid *stp;	unsigned int share_access;	dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 			(int)cstate->current_fh.fh_dentry->d_name.len,			cstate->current_fh.fh_dentry->d_name.name);	if (!access_valid(od->od_share_access)			|| !deny_valid(od->od_share_deny))		return nfserr_inval;	nfs4_lock_state();	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,					od->od_seqid,					&od->od_stateid, 					CHECK_FH | OPEN_STATE, 					&od->od_stateowner, &stp, NULL)))		goto out; 	status = nfserr_inval;	if (!test_bit(od->od_share_access, &stp->st_access_bmap)) {		dprintk("NFSD:access not a subset current bitmap: 0x%lx, input access=%08x\n",			stp->st_access_bmap, od->od_share_access);		goto out;	}	if (!test_bit(od->od_share_deny, &stp->st_deny_bmap)) {		dprintk("NFSD:deny not a subset current bitmap: 0x%lx, input deny=%08x\n",			stp->st_deny_bmap, od->od_share_deny);		goto out;	}	set_access(&share_access, stp->st_access_bmap);	nfs4_file_downgrade(stp->st_vfs_file,	                    share_access & ~od->od_share_access);	reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);	reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);	update_stateid(&stp->st_stateid);	memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));	status = nfs_ok;out:	if (od->od_stateowner) {		nfs4_get_stateowner(od->od_stateowner);		cstate->replay_owner = od->od_stateowner;	}	nfs4_unlock_state();	return status;}/* * nfs4_unlock_state() called after encode */__be32nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	    struct nfsd4_close *close){	__be32 status;	struct nfs4_stateid *stp;	dprintk("NFSD: nfsd4_close on file %.*s\n", 			(int)cstate->current_fh.fh_dentry->d_name.len,			cstate->current_fh.fh_dentry->d_name.name);	nfs4_lock_state();	/* check close_lru for replay */	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,					close->cl_seqid,					&close->cl_stateid, 					CHECK_FH | OPEN_STATE | CLOSE_STATE,					&close->cl_stateowner, &stp, NULL)))		goto out; 	status = nfs_ok;	update_stateid(&stp->st_stateid);	memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));	/* release_stateid() calls nfsd_close() if needed */	release_stateid(stp, OPEN_STATE);	/* place unused nfs4_stateowners on so_close_lru list to be	 * released by the laundromat service after the lease period	 * to enable us to handle CLOSE replay	 */	if (list_empty(&close->cl_stateowner->so_stateids))		move_to_close_lru(close->cl_stateowner);out:	if (close->cl_stateowner) {		nfs4_get_stateowner(close->cl_stateowner);		cstate->replay_owner = close->cl_stateowner;	}	nfs4_unlock_state();	return status;}__be32nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,		  struct nfsd4_delegreturn *dr){	__be32 status;	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))		goto out;	nfs4_lock_state();	status = nfs4_preprocess_stateid_op(&cstate->current_fh,					    &dr->dr_stateid, DELEG_RET, NULL);	nfs4_unlock_state();out:	return status;}/*  * Lock owner state (byte-range locks) */#define LOFF_OVERFLOW(start, len)      ((u64)(len) > ~(u64)(start))#define LOCK_HASH_BITS              8#define LOCK_HASH_SIZE             (1 << LOCK_HASH_BITS)#define LOCK_HASH_MASK             (LOCK_HASH_SIZE - 1)#define lockownerid_hashval(id) \        ((id) & LOCK_HASH_MASK)static inline unsigned intlock_ownerstr_hashval(struct inode *inode, u32 cl_id,		struct xdr_netobj *ownername){	return (file_hashval(inode) + cl_id			+ opaque_hashval(ownername->data, ownername->len))		& LOCK_HASH_MASK;}static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];static struct lis

⌨️ 快捷键说明

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