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

📄 vfs.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 3 页
字号:
nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp){	struct dentry	*dentry;	struct inode	*inode;	mm_segment_t	oldfs;	int		err;	err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP);	if (err)		goto out;	dentry = fhp->fh_dentry;	inode = dentry->d_inode;	err = nfserr_inval;	if (!inode->i_op || !inode->i_op->readlink)		goto out;	UPDATE_ATIME(inode);	/* N.B. Why does this call need a get_fs()??	 * Remove the set_fs and watch the fireworks:-) --okir	 */	oldfs = get_fs(); set_fs(KERNEL_DS);	err = inode->i_op->readlink(dentry, buf, *lenp);	set_fs(oldfs);	if (err < 0)		goto out_nfserr;	*lenp = err;	err = 0;out:	return err;out_nfserr:	err = nfserrno(err);	goto out;}/* * Create a symlink and look up its inode * N.B. After this call _both_ fhp and resfhp need an fh_put */intnfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,				char *fname, int flen,				char *path,  int plen,				struct svc_fh *resfhp,				struct iattr *iap){	struct dentry	*dentry, *dnew;	int		err, cerr;	err = nfserr_noent;	if (!flen || !plen)		goto out;	err = nfserr_exist;	if (isdotent(fname, flen))		goto out;	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);	if (err)		goto out;	fh_lock(fhp);	dentry = fhp->fh_dentry;	dnew = lookup_one_len(fname, dentry, flen);	err = PTR_ERR(dnew);	if (IS_ERR(dnew))		goto out_nfserr;	err = vfs_symlink(dentry->d_inode, dnew, path);	if (!err) {		if (EX_ISSYNC(fhp->fh_export))			nfsd_sync_dir(dentry);		if (iap) {			iap->ia_valid &= ATTR_MODE /* ~(ATTR_MODE|ATTR_UID|ATTR_GID)*/;			if (iap->ia_valid) {				iap->ia_valid |= ATTR_CTIME;				iap->ia_mode = (iap->ia_mode&S_IALLUGO)					| S_IFLNK;				err = notify_change(dnew, iap);				if (!err && EX_ISSYNC(fhp->fh_export))					write_inode_now(dentry->d_inode, 1);		       }		}	} else		err = nfserrno(err);	fh_unlock(fhp);	/* Compose the fh so the dentry will be freed ... */	cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);	if (err==0) err = cerr;out:	return err;out_nfserr:	err = nfserrno(err);	goto out;}/* * Create a hardlink * N.B. After this call _both_ ffhp and tfhp need an fh_put */intnfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,				char *name, int len, struct svc_fh *tfhp){	struct dentry	*ddir, *dnew, *dold;	struct inode	*dirp, *dest;	int		err;	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE);	if (err)		goto out;	err = fh_verify(rqstp, tfhp, -S_IFDIR, MAY_NOP);	if (err)		goto out;	err = nfserr_perm;	if (!len)		goto out;	err = nfserr_exist;	if (isdotent(name, len))		goto out;	fh_lock(ffhp);	ddir = ffhp->fh_dentry;	dirp = ddir->d_inode;	dnew = lookup_one_len(name, ddir, len);	err = PTR_ERR(dnew);	if (IS_ERR(dnew))		goto out_nfserr;	dold = tfhp->fh_dentry;	dest = dold->d_inode;	err = vfs_link(dold, dirp, dnew);	if (!err) {		if (EX_ISSYNC(ffhp->fh_export)) {			nfsd_sync_dir(ddir);			write_inode_now(dest, 1);		}	} else {		if (err == -EXDEV && rqstp->rq_vers == 2)			err = nfserr_acces;		else			err = nfserrno(err);	}	fh_unlock(ffhp);	dput(dnew);out:	return err;out_nfserr:	err = nfserrno(err);	goto out;}/* * Rename a file * N.B. After this call _both_ ffhp and tfhp need an fh_put */intnfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,			    struct svc_fh *tfhp, char *tname, int tlen){	struct dentry	*fdentry, *tdentry, *odentry, *ndentry;	struct inode	*fdir, *tdir;	int		err;	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE);	if (err)		goto out;	err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE);	if (err)		goto out;	fdentry = ffhp->fh_dentry;	fdir = fdentry->d_inode;	tdentry = tfhp->fh_dentry;	tdir = tdentry->d_inode;	err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;	if (fdir->i_dev != tdir->i_dev)		goto out;	err = nfserr_perm;	if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen))		goto out;	/* cannot use fh_lock as we need deadlock protective ordering	 * so do it by hand */	double_down(&tdir->i_sem, &fdir->i_sem);	ffhp->fh_locked = tfhp->fh_locked = 1;	fill_pre_wcc(ffhp);	fill_pre_wcc(tfhp);	odentry = lookup_one_len(fname, fdentry, flen);	err = PTR_ERR(odentry);	if (IS_ERR(odentry))		goto out_nfserr;	err = -ENOENT;	if (!odentry->d_inode)		goto out_dput_old;	ndentry = lookup_one_len(tname, tdentry, tlen);	err = PTR_ERR(ndentry);	if (IS_ERR(ndentry))		goto out_dput_old;#ifdef MSNFS	if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&		((atomic_read(&odentry->d_count) > 1)		 || (atomic_read(&ndentry->d_count) > 1))) {			err = nfserr_perm;	} else#endif	err = vfs_rename(fdir, odentry, tdir, ndentry);	if (!err && EX_ISSYNC(tfhp->fh_export)) {		nfsd_sync_dir(tdentry);		nfsd_sync_dir(fdentry);	}	dput(ndentry); out_dput_old:	dput(odentry); out_nfserr:	if (err)		err = nfserrno(err);	/* we cannot reply on fh_unlock on the two filehandles,	 * as that would do the wrong thing if the two directories	 * were the same, so again we do it by hand	 */	fill_post_wcc(ffhp);	fill_post_wcc(tfhp);	double_up(&tdir->i_sem, &fdir->i_sem);	ffhp->fh_locked = tfhp->fh_locked = 0;	out:	return err;}/* * Unlink a file or directory * N.B. After this call fhp needs an fh_put */intnfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,				char *fname, int flen){	struct dentry	*dentry, *rdentry;	struct inode	*dirp;	int		err;	err = nfserr_acces;	if (!flen || isdotent(fname, flen))		goto out;	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE);	if (err)		goto out;	fh_lock(fhp);	dentry = fhp->fh_dentry;	dirp = dentry->d_inode;	rdentry = lookup_one_len(fname, dentry, flen);	err = PTR_ERR(rdentry);	if (IS_ERR(rdentry))		goto out_nfserr;	if (!rdentry->d_inode) {		dput(rdentry);		err = nfserr_noent;		goto out;	}	if (type != S_IFDIR) { /* It's UNLINK */#ifdef MSNFS		if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&			(atomic_read(&rdentry->d_count) > 1)) {			err = nfserr_perm;		} else#endif		err = vfs_unlink(dirp, rdentry);	} else { /* It's RMDIR */		err = vfs_rmdir(dirp, rdentry);	}	dput(rdentry);	if (err)		goto out_nfserr;	if (EX_ISSYNC(fhp->fh_export)) 		nfsd_sync_dir(dentry);out:	return err;out_nfserr:	err = nfserrno(err);	goto out;}/* * Read entries from a directory. * The verifier is an NFSv3 thing we ignore for now. */intnfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,              encode_dent_fn func, u32 *buffer, int *countp, u32 *verf){	struct inode	*inode;	u32		*p;	int		oldlen, eof, err;	struct file	file;	struct readdir_cd cd;	err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);	if (err)		goto out;	if (offset > ~(u32) 0)		goto out_close;	err = nfserr_notdir;	if (!file.f_op->readdir)		goto out_close;	file.f_pos = offset;	/* Set up the readdir context */	memset(&cd, 0, sizeof(cd));	cd.rqstp  = rqstp;	cd.buffer = buffer;	cd.buflen = *countp; /* count of words */	cd.dirfh  = fhp;	/*	 * Read the directory entries. This silly loop is necessary because	 * readdir() is not guaranteed to fill up the entire buffer, but	 * may choose to do less.	 */	inode = file.f_dentry->d_inode;	down(&inode->i_sem);	while (1) {		oldlen = cd.buflen;		/*		dprintk("nfsd: f_op->readdir(%x/%ld @ %d) buflen = %d (%d)\n",			file.f_inode->i_dev, file.f_inode->i_ino,			(int) file.f_pos, (int) oldlen, (int) cd.buflen);		 */		err = file.f_op->readdir(&file, &cd, (filldir_t) func);		if (err < 0)			goto out_nfserr;		if (oldlen == cd.buflen)			break;		if (cd.eob)			break;	}	up(&inode->i_sem);	/* If we didn't fill the buffer completely, we're at EOF */	eof = !cd.eob;	if (cd.offset) {		if (rqstp->rq_vers == 3)			(void)xdr_encode_hyper(cd.offset, file.f_pos);		else			*cd.offset = htonl(file.f_pos);	}	p = cd.buffer;	*p++ = 0;			/* no more entries */	*p++ = htonl(eof);		/* end of directory */	*countp = (caddr_t) p - (caddr_t) buffer;	dprintk("nfsd: readdir result %d bytes, eof %d offset %d\n",				*countp, eof,				cd.offset? ntohl(*cd.offset) : -1);	err = 0;out_close:	nfsd_close(&file);out:	return err;out_nfserr:	up(&inode->i_sem);	err = nfserrno(err);	goto out_close;}/* * Get file system stats * N.B. After this call fhp needs an fh_put */intnfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct statfs *stat){	int err = fh_verify(rqstp, fhp, 0, MAY_NOP);	if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat))		err = nfserr_io;	return err;}/* * Check for a user's access permissions to this inode. */intnfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc){	struct inode	*inode = dentry->d_inode;	int		err;	if (acc == MAY_NOP)		return 0;#if 0	dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",		acc,		(acc & MAY_READ)?	" read"  : "",		(acc & MAY_WRITE)?	" write" : "",		(acc & MAY_EXEC)?	" exec"  : "",		(acc & MAY_SATTR)?	" sattr" : "",		(acc & MAY_TRUNC)?	" trunc" : "",		(acc & MAY_LOCK)?	" lock"  : "",		(acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "",		inode->i_mode,		IS_IMMUTABLE(inode)?	" immut" : "",		IS_APPEND(inode)?	" append" : "",		IS_RDONLY(inode)?	" ro" : "");	dprintk("      owner %d/%d user %d/%d\n",		inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);#endif	/* only care about readonly exports for files and	 * directories. links don't have meaningful write access,	 * and all else is local to the client	 */	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) 		if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {			if (EX_RDONLY(exp) || IS_RDONLY(inode))				return nfserr_rofs;			if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))				return nfserr_perm;		}	if ((acc & MAY_TRUNC) && IS_APPEND(inode))		return nfserr_perm;	if (acc & MAY_LOCK) {		/* If we cannot rely on authentication in NLM requests,		 * just allow locks, otherwise require read permission, or		 * ownership		 */		if (exp->ex_flags & NFSEXP_NOAUTHNLM)			return 0;		else			acc = MAY_READ | MAY_OWNER_OVERRIDE;	}	/*	 * The file owner always gets access permission for accesses that	 * would normally be checked at open time. This is to make	 * file access work even when the client has done a fchmod(fd, 0).	 *	 * However, `cp foo bar' should fail nevertheless when bar is	 * readonly. A sensible way to do this might be to reject all	 * attempts to truncate a read-only file, because a creat() call	 * always implies file truncation.	 * ... but this isn't really fair.  A process may reasonably call	 * ftruncate on an open file descriptor on a file with perm 000.	 * We must trust the client to do permission checking - using "ACCESS"	 * with NFSv3.	 */	if ((acc & MAY_OWNER_OVERRIDE) &&	    inode->i_uid == current->fsuid)		return 0;	acc &= ~ MAY_OWNER_OVERRIDE; /* This bit is no longer needed,                                        and gets in the way later */	err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC));	/* Allow read access to binaries even when mode 111 */	if (err == -EACCES && S_ISREG(inode->i_mode) && acc == MAY_READ)		err = permission(inode, MAY_EXEC);	return err? nfserrno(err) : 0;}voidnfsd_racache_shutdown(void){	if (!raparm_cache)		return;	dprintk("nfsd: freeing readahead buffers.\n");	kfree(raparml);	raparm_cache = raparml = NULL;}/* * Initialize readahead param cache */intnfsd_racache_init(int cache_size){	int	i;	if (raparm_cache)		return 0;	raparml = kmalloc(sizeof(struct raparms) * cache_size, GFP_KERNEL);	if (raparml != NULL) {		dprintk("nfsd: allocating %d readahead buffers.\n",			cache_size);		memset(raparml, 0, sizeof(struct raparms) * cache_size);		for (i = 0; i < cache_size - 1; i++) {			raparml[i].p_next = raparml + i + 1;		}		raparm_cache = raparml;	} else {		printk(KERN_WARNING		       "nfsd: Could not allocate memory read-ahead cache.\n");		return -ENOMEM;	}	nfsdstats.ra_size = cache_size;	return 0;}

⌨️ 快捷键说明

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