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

📄 vfs.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct inode *inode = dp->d_inode;	int (*fsync) (struct file *, struct dentry *, int);		if (inode->i_fop && (fsync = inode->i_fop->fsync)) {		fsync(NULL, dp, 0);	}}/* * Obtain the readahead parameters for the file * specified by (dev, ino). */static inline struct raparms *nfsd_get_raparms(dev_t dev, ino_t ino){	struct raparms	*ra, **rap, **frap = NULL;	int depth = 0;		for (rap = &raparm_cache; (ra = *rap); rap = &ra->p_next) {		if (ra->p_ino == ino && ra->p_dev == dev)			goto found;		depth++;		if (ra->p_count == 0)			frap = rap;	}	depth = nfsdstats.ra_size*11/10;	if (!frap)		return NULL;	rap = frap;	ra = *frap;	ra->p_dev = dev;	ra->p_ino = ino;	ra->p_reada = 0;	ra->p_ramax = 0;	ra->p_raend = 0;	ra->p_ralen = 0;	ra->p_rawin = 0;found:	if (rap != &raparm_cache) {		*rap = ra->p_next;		ra->p_next   = raparm_cache;		raparm_cache = ra;	}	ra->p_count++;	nfsdstats.ra_depth[depth*10/nfsdstats.ra_size]++;	return ra;}/* * Read data from a file. count must contain the requested read count * on entry. On return, *count contains the number of bytes actually read. * N.B. After this call fhp needs an fh_put */intnfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,          char *buf, unsigned long *count){	struct raparms	*ra;	mm_segment_t	oldfs;	int		err;	struct file	file;	err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);	if (err)		goto out;	err = nfserr_perm;	if (!file.f_op->read)		goto out_close;#ifdef MSNFS	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&		(!lock_may_read(file.f_dentry->d_inode, offset, *count)))		goto out_close;#endif	/* Get readahead parameters */	ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino);	if (ra) {		file.f_reada = ra->p_reada;		file.f_ramax = ra->p_ramax;		file.f_raend = ra->p_raend;		file.f_ralen = ra->p_ralen;		file.f_rawin = ra->p_rawin;	}	file.f_pos = offset;	oldfs = get_fs(); set_fs(KERNEL_DS);	err = file.f_op->read(&file, buf, *count, &file.f_pos);	set_fs(oldfs);	/* Write back readahead params */	if (ra != NULL) {		dprintk("nfsd: raparms %ld %ld %ld %ld %ld\n",			file.f_reada, file.f_ramax, file.f_raend,			file.f_ralen, file.f_rawin);		ra->p_reada = file.f_reada;		ra->p_ramax = file.f_ramax;		ra->p_raend = file.f_raend;		ra->p_ralen = file.f_ralen;		ra->p_rawin = file.f_rawin;		ra->p_count -= 1;	}	if (err >= 0) {		nfsdstats.io_read += err;		*count = err;		err = 0;	} else 		err = nfserrno(err);out_close:	nfsd_close(&file);out:	return err;}/* * Write data to a file. * The stable flag requests synchronous writes. * N.B. After this call fhp needs an fh_put */intnfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,				char *buf, unsigned long cnt, int *stablep){	struct svc_export	*exp;	struct file		file;	struct dentry		*dentry;	struct inode		*inode;	mm_segment_t		oldfs;	int			err = 0;	int			stable = *stablep;	err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file);	if (err)		goto out;	if (!cnt)		goto out_close;	err = nfserr_perm;	if (!file.f_op->write)		goto out_close;#ifdef MSNFS	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&		(!lock_may_write(file.f_dentry->d_inode, offset, cnt)))		goto out_close;#endif	dentry = file.f_dentry;	inode = dentry->d_inode;	exp   = fhp->fh_export;	/*	 * Request sync writes if	 *  -	the sync export option has been set, or	 *  -	the client requested O_SYNC behavior (NFSv3 feature).	 *  -   The file system doesn't support fsync().	 * When gathered writes have been configured for this volume,	 * flushing the data to disk is handled separately below.	 */	if (file.f_op->fsync == 0) {/* COMMIT3 cannot work */	       stable = 2;	       *stablep = 2; /* FILE_SYNC */	}	if (!EX_ISSYNC(exp))		stable = 0;	if (stable && !EX_WGATHER(exp))		file.f_flags |= O_SYNC;	file.f_pos = offset;		/* set write offset */	/* Write the data. */	oldfs = get_fs(); set_fs(KERNEL_DS);	err = file.f_op->write(&file, buf, cnt, &file.f_pos);	if (err >= 0)		nfsdstats.io_write += cnt;	set_fs(oldfs);	/* clear setuid/setgid flag after write */	if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {		struct iattr	ia;		ia.ia_valid = ATTR_MODE;		ia.ia_mode  = inode->i_mode & ~(S_ISUID | S_ISGID);		notify_change(dentry, &ia);	}	if (err >= 0 && stable) {		static unsigned long	last_ino;		static kdev_t		last_dev = NODEV;		/*		 * Gathered writes: If another process is currently		 * writing to the file, there's a high chance		 * this is another nfsd (triggered by a bulk write		 * from a client's biod). Rather than syncing the		 * file with each write request, we sleep for 10 msec.		 *		 * I don't know if this roughly approximates		 * C. Juszak's idea of gathered writes, but it's a		 * nice and simple solution (IMHO), and it seems to		 * work:-)		 */		if (EX_WGATHER(exp)) {			if (atomic_read(&inode->i_writecount) > 1			    || (last_ino == inode->i_ino && last_dev == inode->i_dev)) {				dprintk("nfsd: write defer %d\n", current->pid);				set_current_state(TASK_UNINTERRUPTIBLE);				schedule_timeout((HZ+99)/100);				current->state = TASK_RUNNING;				dprintk("nfsd: write resume %d\n", current->pid);			}			if (inode->i_state & I_DIRTY) {				dprintk("nfsd: write sync %d\n", current->pid);				nfsd_sync(&file);			}#if 0			wake_up(&inode->i_wait);#endif		}		last_ino = inode->i_ino;		last_dev = inode->i_dev;	}	dprintk("nfsd: write complete err=%d\n", err);	if (err >= 0)		err = 0;	else 		err = nfserrno(err);out_close:	nfsd_close(&file);out:	return err;}#ifdef CONFIG_NFSD_V3/* * Commit all pending writes to stable storage. * Strictly speaking, we could sync just the indicated file region here, * but there's currently no way we can ask the VFS to do so. * * Unfortunately we cannot lock the file to make sure we return full WCC * data to the client, as locking happens lower down in the filesystem. */intnfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,               off_t offset, unsigned long count){	struct file	file;	int		err;	if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)		return err;	if (EX_ISSYNC(fhp->fh_export)) {		if (file.f_op && file.f_op->fsync) {			nfsd_sync(&file);		} else {			err = nfserr_notsupp;		}	}	nfsd_close(&file);	return err;}#endif /* CONFIG_NFSD_V3 *//* * Create a file (regular, directory, device, fifo); UNIX sockets  * not yet implemented. * If the response fh has been verified, the parent directory should * already be locked. Note that the parent directory is left locked. * * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp */intnfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,		char *fname, int flen, struct iattr *iap,		int type, dev_t rdev, struct svc_fh *resfhp){	struct dentry	*dentry, *dchild;	struct inode	*dirp;	int		err;	err = nfserr_perm;	if (!flen)		goto out;	err = nfserr_exist;	if (isdotent(fname, flen))		goto out;	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);	if (err)		goto out;	dentry = fhp->fh_dentry;	dirp = dentry->d_inode;	err = nfserr_notdir;	if(!dirp->i_op || !dirp->i_op->lookup)		goto out;	/*	 * Check whether the response file handle has been verified yet.	 * If it has, the parent directory should already be locked.	 */	if (!resfhp->fh_dentry) {		/* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */		fh_lock(fhp);		dchild = lookup_one_len(fname, dentry, flen);		err = PTR_ERR(dchild);		if (IS_ERR(dchild))			goto out_nfserr;		err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);		if (err)			goto out;	} else {		/* called from nfsd_proc_create */		dchild = resfhp->fh_dentry;		if (!fhp->fh_locked) {			/* not actually possible */			printk(KERN_ERR				"nfsd_create: parent %s/%s not locked!\n",				dentry->d_parent->d_name.name,				dentry->d_name.name);			err = -EIO;			goto out;		}	}	/*	 * Make sure the child dentry is still negative ...	 */	err = nfserr_exist;	if (dchild->d_inode) {		dprintk("nfsd_create: dentry %s/%s not negative!\n",			dentry->d_name.name, dchild->d_name.name);		goto out; 	}	if (!(iap->ia_valid & ATTR_MODE))		iap->ia_mode = 0;	iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;	/*	 * Get the dir op function pointer.	 */	err = nfserr_perm;	switch (type) {	case S_IFREG:		err = vfs_create(dirp, dchild, iap->ia_mode);		break;	case S_IFDIR:		err = vfs_mkdir(dirp, dchild, iap->ia_mode);		break;	case S_IFCHR:	case S_IFBLK:	case S_IFIFO:	case S_IFSOCK:		err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);		break;	default:	        printk("nfsd: bad file type %o in nfsd_create\n", type);		err = -EINVAL;	}	if (err < 0)		goto out_nfserr;	if (EX_ISSYNC(fhp->fh_export)) {		nfsd_sync_dir(dentry);		write_inode_now(dchild->d_inode, 1);	}	/* Set file attributes. Mode has already been set and	 * setting uid/gid works only for root. Irix appears to	 * send along the gid when it tries to implement setgid	 * directories via NFS.	 */	err = 0;	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)		err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);	/*	 * Update the file handle to get the new inode info.	 */	if (!err)		err = fh_update(resfhp);out:	return err;out_nfserr:	err = nfserrno(err);	goto out;}#ifdef CONFIG_NFSD_V3/* * NFSv3 version of nfsd_create */intnfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,		char *fname, int flen, struct iattr *iap,		struct svc_fh *resfhp, int createmode, u32 *verifier){	struct dentry	*dentry, *dchild;	struct inode	*dirp;	int		err;	__u32		v_mtime=0, v_atime=0;	int		v_mode=0;	err = nfserr_perm;	if (!flen)		goto out;	err = nfserr_exist;	if (isdotent(fname, flen))		goto out;	if (!(iap->ia_valid & ATTR_MODE))		iap->ia_mode = 0;	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);	if (err)		goto out;	dentry = fhp->fh_dentry;	dirp = dentry->d_inode;	/* Get all the sanity checks out of the way before	 * we lock the parent. */	err = nfserr_notdir;	if(!dirp->i_op || !dirp->i_op->lookup)		goto out;	fh_lock(fhp);	/*	 * Compose the response file handle.	 */	dchild = lookup_one_len(fname, dentry, flen);	err = PTR_ERR(dchild);	if (IS_ERR(dchild))		goto out_nfserr;	err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);	if (err)		goto out;	if (createmode == NFS3_CREATE_EXCLUSIVE) {		/* while the verifier would fit in mtime+atime,		 * solaris7 gets confused (bugid 4218508) if these have		 * the high bit set, so we use the mode as well		 */		v_mtime = verifier[0]&0x7fffffff;		v_atime = verifier[1]&0x7fffffff;		v_mode  = S_IFREG			| ((verifier[0]&0x80000000) >> (32-7)) /* u+x */			| ((verifier[1]&0x80000000) >> (32-9)) /* u+r */			;	}		if (dchild->d_inode) {		err = 0;		switch (createmode) {		case NFS3_CREATE_UNCHECKED:			if (! S_ISREG(dchild->d_inode->i_mode))				err = nfserr_exist;			else {				iap->ia_valid &= ATTR_SIZE;				goto set_attr;			}			break;		case NFS3_CREATE_EXCLUSIVE:			if (   dchild->d_inode->i_mtime == v_mtime			    && dchild->d_inode->i_atime == v_atime			    && dchild->d_inode->i_mode  == v_mode			    && dchild->d_inode->i_size  == 0 )				break;			 /* fallthru */		case NFS3_CREATE_GUARDED:			err = nfserr_exist;		}		goto out;	}	err = vfs_create(dirp, dchild, iap->ia_mode);	if (err < 0)		goto out_nfserr;	if (EX_ISSYNC(fhp->fh_export)) {		nfsd_sync_dir(dentry);		/* setattr will sync the child (or not) */	}	/*	 * Update the filehandle to get the new inode info.	 */	err = fh_update(resfhp);	if (err)		goto out;	if (createmode == NFS3_CREATE_EXCLUSIVE) {		/* Cram the verifier into atime/mtime/mode */		iap->ia_valid = ATTR_MTIME|ATTR_ATIME			| ATTR_MTIME_SET|ATTR_ATIME_SET			| ATTR_MODE;		iap->ia_mtime = v_mtime;		iap->ia_atime = v_atime;		iap->ia_mode  = v_mode;	}	/* Set file attributes.	 * Mode has already been set but we might need to reset it	 * for CREATE_EXCLUSIVE	 * Irix appears to send along the gid when it tries to	 * implement setgid directories via NFS. Clear out all that cruft.	 */ set_attr:	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) 		err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); out:	fh_unlock(fhp); 	return err;  out_nfserr:	err = nfserrno(err);	goto out;}#endif /* CONFIG_NFSD_V3 *//* * Read a symlink. On entry, *lenp must contain the maximum path length that * fits into the buffer. On return, it contains the true length. * N.B. After this call fhp needs an fh_put */int

⌨️ 快捷键说明

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