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

📄 dir.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Called when the dentry loses inode. * We use it to clean up silly-renamed files. */static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode){	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {		lock_kernel();		nfs_complete_unlink(dentry);		unlock_kernel();	}	iput(inode);}struct dentry_operations nfs_dentry_operations = {	d_revalidate:	nfs_lookup_revalidate,	d_delete:	nfs_dentry_delete,	d_iput:		nfs_dentry_iput,};static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry){	struct inode *inode;	int error;	struct nfs_fh fhandle;	struct nfs_fattr fattr;	dfprintk(VFS, "NFS: lookup(%s/%s)\n",		dentry->d_parent->d_name.name, dentry->d_name.name);	error = -ENAMETOOLONG;	if (dentry->d_name.len > NFS_SERVER(dir)->namelen)		goto out;	error = -ENOMEM;	dentry->d_op = &nfs_dentry_operations;	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);	inode = NULL;	if (error == -ENOENT)		goto no_entry;	if (!error) {		error = -EACCES;		inode = nfs_fhget(dentry, &fhandle, &fattr);		if (inode) {	    no_entry:			d_add(dentry, inode);			nfs_renew_times(dentry);			error = 0;		}	}out:	return ERR_PTR(error);}/* * Code common to create, mkdir, and mknod. */static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,				struct nfs_fattr *fattr){	struct inode *inode;	int error = -EACCES;	inode = nfs_fhget(dentry, fhandle, fattr);	if (inode) {		d_instantiate(dentry, inode);		nfs_renew_times(dentry);		error = 0;	}	return error;}/* * Following a failed create operation, we drop the dentry rather * than retain a negative dentry. This avoids a problem in the event * that the operation succeeded on the server, but an error in the * reply path made it appear to have failed. */static int nfs_create(struct inode *dir, struct dentry *dentry, int mode){	struct iattr attr;	struct nfs_fattr fattr;	struct nfs_fh fhandle;	int error;	dfprintk(VFS, "NFS: create(%x/%ld, %s\n",		dir->i_dev, dir->i_ino, dentry->d_name.name);	attr.ia_mode = mode;	attr.ia_valid = ATTR_MODE;	/*	 * The 0 argument passed into the create function should one day	 * contain the O_EXCL flag if requested. This allows NFSv3 to	 * select the appropriate create strategy. Currently open_namei	 * does not pass the create flags.	 */	nfs_zap_caches(dir);	error = NFS_PROTO(dir)->create(dir, &dentry->d_name,					 &attr, 0, &fhandle, &fattr);	if (!error && fhandle.size != 0)		error = nfs_instantiate(dentry, &fhandle, &fattr);	if (error || fhandle.size == 0)		d_drop(dentry);	return error;}/* * See comments for nfs_proc_create regarding failed operations. */static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev){	struct iattr attr;	struct nfs_fattr fattr;	struct nfs_fh fhandle;	int error;	dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",		dir->i_dev, dir->i_ino, dentry->d_name.name);	attr.ia_mode = mode;	attr.ia_valid = ATTR_MODE;	nfs_zap_caches(dir);	error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,					&fhandle, &fattr);	if (!error && fhandle.size != 0)		error = nfs_instantiate(dentry, &fhandle, &fattr);	if (error || fhandle.size == 0)		d_drop(dentry);	return error;}/* * See comments for nfs_proc_create regarding failed operations. */static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode){	struct iattr attr;	struct nfs_fattr fattr;	struct nfs_fh fhandle;	int error;	dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",		dir->i_dev, dir->i_ino, dentry->d_name.name);	attr.ia_valid = ATTR_MODE;	attr.ia_mode = mode | S_IFDIR;#if 0	/*	 * Always drop the dentry, we can't always depend on	 * the fattr returned by the server (AIX seems to be	 * broken). We're better off doing another lookup than	 * depending on potentially bogus information.	 */	d_drop(dentry);#endif	nfs_zap_caches(dir);	error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,					&fattr);	if (!error && fhandle.size != 0)		error = nfs_instantiate(dentry, &fhandle, &fattr);	if (error || fhandle.size == 0)		d_drop(dentry);	return error;}static int nfs_rmdir(struct inode *dir, struct dentry *dentry){	int error;	dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",		dir->i_dev, dir->i_ino, dentry->d_name.name);	nfs_zap_caches(dir);	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);	if (!error)		dentry->d_inode->i_nlink = 0;	return error;}static int nfs_sillyrename(struct inode *dir, struct dentry *dentry){	static unsigned int sillycounter;	const int      i_inosize  = sizeof(dir->i_ino)*2;	const int      countersize = sizeof(sillycounter)*2;	const int      slen       = strlen(".nfs") + i_inosize + countersize;	char           silly[slen+1];	struct qstr    qsilly;	struct dentry *sdentry;	int            error = -EIO;	dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",		dentry->d_parent->d_name.name, dentry->d_name.name, 		atomic_read(&dentry->d_count));	if (atomic_read(&dentry->d_count) == 1)		goto out;  /* No need to silly rename. */#ifdef NFS_PARANOIAif (!dentry->d_inode)printk("NFS: silly-renaming %s/%s, negative dentry??\n",dentry->d_parent->d_name.name, dentry->d_name.name);#endif	/*	 * We don't allow a dentry to be silly-renamed twice.	 */	error = -EBUSY;	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)		goto out;	sprintf(silly, ".nfs%*.*lx",		i_inosize, i_inosize, dentry->d_inode->i_ino);	sdentry = NULL;	do {		char *suffix = silly + slen - countersize;		dput(sdentry);		sillycounter++;		sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);		dfprintk(VFS, "trying to rename %s to %s\n",			 dentry->d_name.name, silly);				sdentry = lookup_one_len(silly, dentry->d_parent, slen);		/*		 * N.B. Better to return EBUSY here ... it could be		 * dangerous to delete the file while it's in use.		 */		if (IS_ERR(sdentry))			goto out;	} while(sdentry->d_inode != NULL); /* need negative lookup */	nfs_zap_caches(dir);	qsilly.name = silly;	qsilly.len  = strlen(silly);	error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, dir, &qsilly);	if (!error) {		nfs_renew_times(dentry);		d_move(dentry, sdentry);		error = nfs_async_unlink(dentry); 		/* If we return 0 we don't unlink */	}	dput(sdentry);out:	return error;}/* * Remove a file after making sure there are no pending writes, * and after checking that the file has only one user.  * * We invalidate the attribute cache and free the inode prior to the operation * to avoid possible races if the server reuses the inode. */static int nfs_safe_remove(struct dentry *dentry){	struct inode *dir = dentry->d_parent->d_inode;	struct inode *inode = dentry->d_inode;	int error = -EBUSY, rehash = 0;			dfprintk(VFS, "NFS: safe_remove(%s/%s)\n",		dentry->d_parent->d_name.name, dentry->d_name.name);	/*	 * Unhash the dentry while we remove the file ...	 */	if (!d_unhashed(dentry)) {		d_drop(dentry);		rehash = 1;	}	if (atomic_read(&dentry->d_count) > 1) {#ifdef NFS_PARANOIA		printk("nfs_safe_remove: %s/%s busy, d_count=%d\n",			dentry->d_parent->d_name.name, dentry->d_name.name,			atomic_read(&dentry->d_count));#endif		goto out;	}	/* If the dentry was sillyrenamed, we simply call d_delete() */	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {		error = 0;		goto out_delete;	}	nfs_zap_caches(dir);	if (inode)		NFS_CACHEINV(inode);	error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);	if (error < 0)		goto out;	if (inode)		inode->i_nlink--; out_delete:	/*	 * Free the inode	 */	d_delete(dentry);out:	if (rehash)		d_rehash(dentry);	return error;}/*  We do silly rename. In case sillyrename() returns -EBUSY, the inode *  belongs to an active ".nfs..." file and we return -EBUSY. * *  If sillyrename() returns 0, we do nothing, otherwise we unlink. */static int nfs_unlink(struct inode *dir, struct dentry *dentry){	int error;	dfprintk(VFS, "NFS: unlink(%x/%ld, %s)\n",		dir->i_dev, dir->i_ino, dentry->d_name.name);	error = nfs_sillyrename(dir, dentry);	if (error && error != -EBUSY) {		error = nfs_safe_remove(dentry);		if (!error) {			nfs_renew_times(dentry);		}	}	return error;}static intnfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname){	struct iattr attr;	struct nfs_fattr sym_attr;	struct nfs_fh sym_fh;	struct qstr qsymname;	unsigned int maxlen;	int error;	dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",		dir->i_dev, dir->i_ino, dentry->d_name.name, symname);	error = -ENAMETOOLONG;	maxlen = (NFS_PROTO(dir)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN;	if (strlen(symname) > maxlen)		goto out;#ifdef NFS_PARANOIAif (dentry->d_inode)printk("nfs_proc_symlink: %s/%s not negative!\n",dentry->d_parent->d_name.name, dentry->d_name.name);#endif	/*	 * Fill in the sattr for the call. 	 * Note: SunOS 4.1.2 crashes if the mode isn't initialized!	 */	attr.ia_valid = ATTR_MODE;	attr.ia_mode = S_IFLNK | S_IRWXUGO;	qsymname.name = symname;	qsymname.len  = strlen(symname);	nfs_zap_caches(dir);	error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,					  &attr, &sym_fh, &sym_attr);	if (!error && sym_fh.size != 0 && (sym_attr.valid & NFS_ATTR_FATTR)) {		error = nfs_instantiate(dentry, &sym_fh, &sym_attr);	} else {		if (error == -EEXIST)			printk("nfs_proc_symlink: %s/%s already exists??\n",			       dentry->d_parent->d_name.name, dentry->d_name.name);		d_drop(dentry);	}out:	return error;}static int nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry){	struct inode *inode = old_dentry->d_inode;	int error;	dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n",		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,		dentry->d_parent->d_name.name, dentry->d_name.name);	/*	 * Drop the dentry in advance to force a new lookup.	 * Since nfs_proc_link doesn't return a file handle,	 * we can't use the existing dentry.	 */	d_drop(dentry);	nfs_zap_caches(dir);	NFS_CACHEINV(inode);	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);	return error;}/* * RENAME * FIXME: Some nfsds, like the Linux user space nfsd, may generate a * different file handle for the same inode after a rename (e.g. when * moving to a different directory). A fail-safe method to do so would * be to look up old_dir/old_name, create a link to new_dir/new_name and * rename the old file using the sillyrename stuff. This way, the original * file in old_dir will go away when the last process iput()s the inode. * * FIXED. *  * It actually works quite well. One needs to have the possibility for * at least one ".nfs..." file in each directory the file ever gets * moved or linked to which happens automagically with the new * implementation that only depends on the dcache stuff instead of * using the inode layer * * Unfortunately, things are a little more complicated than indicated * above. For a cross-directory move, we want to make sure we can get * rid of the old inode after the operation.  This means there must be * no pending writes (if it's a file), and the use count must be 1. * If these conditions are met, we can drop the dentries before doing * the rename. */static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,		      struct inode *new_dir, struct dentry *new_dentry){	struct inode *old_inode = old_dentry->d_inode;	struct inode *new_inode = new_dentry->d_inode;	struct dentry *dentry = NULL, *rehash = NULL;	int error = -EBUSY;	/*	 * To prevent any new references to the target during the rename,	 * we unhash the dentry and free the inode in advance.	 */	if (!d_unhashed(new_dentry)) {		d_drop(new_dentry);		rehash = new_dentry;	}	dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",		 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,		 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,		 atomic_read(&new_dentry->d_count));	/*	 * First check whether the target is busy ... we can't	 * safely do _any_ rename if the target is in use.	 *	 * For files, make a copy of the dentry and then do a 	 * silly-rename. If the silly-rename succeeds, the	 * copied dentry is hashed and becomes the new target.	 */	if (!new_inode)		goto go_ahead;	if (S_ISDIR(new_inode->i_mode))		goto out;	else if (atomic_read(&new_dentry->d_count) > 1) {		int err;		/* copy the target dentry's name */		dentry = d_alloc(new_dentry->d_parent,				 &new_dentry->d_name);		if (!dentry)			goto out;		/* silly-rename the existing target ... */		err = nfs_sillyrename(new_dir, new_dentry);		if (!err) {			new_dentry = rehash = dentry;			new_inode = NULL;			/* instantiate the replacement target */			d_instantiate(new_dentry, NULL);		}		/* dentry still busy? */		if (atomic_read(&new_dentry->d_count) > 1) {#ifdef NFS_PARANOIA			printk("nfs_rename: target %s/%s busy, d_count=%d\n",			       new_dentry->d_parent->d_name.name,			       new_dentry->d_name.name,			       atomic_read(&new_dentry->d_count));#endif			goto out;		}	}go_ahead:	/*	 * ... prune child dentries and writebacks if needed.	 */	if (atomic_read(&old_dentry->d_count) > 1) {		nfs_wb_all(old_inode);		shrink_dcache_parent(old_dentry);	}	if (new_inode)		d_delete(new_dentry);	nfs_zap_caches(new_dir);	nfs_zap_caches(old_dir);	error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,					   new_dir, &new_dentry->d_name);out:	if (rehash)		d_rehash(rehash);	if (!error && !S_ISDIR(old_inode->i_mode))		d_move(old_dentry, new_dentry);	/* new dentry created? */	if (dentry)		dput(dentry);	return error;}intnfs_permission(struct inode *inode, int mask){	int			error = vfs_permission(inode, mask);	if (!NFS_PROTO(inode)->access)		goto out;	if (error == -EROFS)		goto out;	/*	 * Trust UNIX mode bits except:	 *	 * 1) When override capabilities may have been invoked	 * 2) When root squashing may be involved	 * 3) When ACLs may overturn a negative answer */	if (!capable(CAP_DAC_OVERRIDE) && !capable(CAP_DAC_READ_SEARCH)	    && (current->fsuid != 0) && (current->fsgid != 0)	    && error != -EACCES)		goto out;	error = NFS_PROTO(inode)->access(inode, mask, 0);	if (error == -EACCES && NFS_CLIENT(inode)->cl_droppriv &&	    current->uid != 0 && current->gid != 0 &&	    (current->fsuid != current->uid || current->fsgid != current->gid))		error = NFS_PROTO(inode)->access(inode, mask, 1); out:	return error;}/* * Local variables: *  version-control: t *  kept-new-versions: 5 * End: */

⌨️ 快捷键说明

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