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

📄 inode.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 4 页
字号:
		} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)			tmp_inode->i_fop = &cifs_file_nobrl_ops;		else			tmp_inode->i_fop = &cifs_file_ops;		if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&		   (cifs_sb->tcon->ses->server->maxBuf <			PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))			tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;		else			tmp_inode->i_data.a_ops = &cifs_addr_ops;		if (isNewInode)			return; /* No sense invalidating pages for new inode				   since we we have not started caching				   readahead file data yet */		if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&			(local_size == tmp_inode->i_size)) {			cFYI(1, ("inode exists but unchanged"));		} else {			/* file may have changed on server */			cFYI(1, ("invalidate inode, readdir detected change"));			invalidate_remote_inode(tmp_inode);		}	} else if (S_ISDIR(tmp_inode->i_mode)) {		cFYI(1, ("Directory inode"));		tmp_inode->i_op = &cifs_dir_inode_ops;		tmp_inode->i_fop = &cifs_dir_ops;	} else if (S_ISLNK(tmp_inode->i_mode)) {		cFYI(1, ("Symbolic Link inode"));		tmp_inode->i_op = &cifs_symlink_inode_ops;/* tmp_inode->i_fop = *//* do not need to set to anything */	} else {		cFYI(1, ("Special inode"));		init_special_inode(tmp_inode, tmp_inode->i_mode,				   tmp_inode->i_rdev);	}}int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode){	int rc = 0;	int xid;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	char *full_path = NULL;	struct inode *newinode = NULL;	cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));	xid = GetXid();	cifs_sb = CIFS_SB(inode->i_sb);	pTcon = cifs_sb->tcon;	full_path = build_path_from_dentry(direntry);	if (full_path == NULL) {		FreeXid(xid);		return -ENOMEM;	}	if ((pTcon->ses->capabilities & CAP_UNIX) &&		(CIFS_UNIX_POSIX_PATH_OPS_CAP &			le64_to_cpu(pTcon->fsUnixInfo.Capability))) {		u32 oplock = 0;		FILE_UNIX_BASIC_INFO * pInfo =			kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);		if (pInfo == NULL) {			rc = -ENOMEM;			goto mkdir_out;		}		mode &= ~current->fs->umask;		rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,				mode, NULL /* netfid */, pInfo, &oplock,				full_path, cifs_sb->local_nls,				cifs_sb->mnt_cifs_flags &					CIFS_MOUNT_MAP_SPECIAL_CHR);		if (rc == -EOPNOTSUPP) {			kfree(pInfo);			goto mkdir_retry_old;		} else if (rc) {			cFYI(1, ("posix mkdir returned 0x%x", rc));			d_drop(direntry);		} else {			int obj_type;			if (pInfo->Type == -1) /* no return info - go query */ {				kfree(pInfo);				goto mkdir_get_info;			}/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need	to set uid/gid */			inc_nlink(inode);			if (pTcon->nocase)				direntry->d_op = &cifs_ci_dentry_ops;			else				direntry->d_op = &cifs_dentry_ops;			newinode = new_inode(inode->i_sb);			if (newinode == NULL) {				kfree(pInfo);				goto mkdir_get_info;			}			/* Is an i_ino of zero legal? */			/* Are there sanity checks we can use to ensure that			   the server is really filling in that field? */			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {				newinode->i_ino =					(unsigned long)pInfo->UniqueId;			} /* note ino incremented to unique num in new_inode */			if (inode->i_sb->s_flags & MS_NOATIME)				newinode->i_flags |= S_NOATIME | S_NOCMTIME;			newinode->i_nlink = 2;			insert_inode_hash(newinode);			d_instantiate(direntry, newinode);			/* we already checked in POSIXCreate whether			   frame was long enough */			posix_fill_in_inode(direntry->d_inode,					pInfo, &obj_type, 1 /* NewInode */);#ifdef CONFIG_CIFS_DEBUG2			cFYI(1, ("instantiated dentry %p %s to inode %p",				direntry, direntry->d_name.name, newinode));			if (newinode->i_nlink != 2)				cFYI(1, ("unexpected number of links %d",					newinode->i_nlink));#endif		}		kfree(pInfo);		goto mkdir_out;	}mkdir_retry_old:	/* BB add setting the equivalent of mode via CreateX w/ACLs */	rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);	if (rc) {		cFYI(1, ("cifs_mkdir returned 0x%x", rc));		d_drop(direntry);	} else {mkdir_get_info:		inc_nlink(inode);		if (pTcon->unix_ext)			rc = cifs_get_inode_info_unix(&newinode, full_path,						      inode->i_sb, xid);		else			rc = cifs_get_inode_info(&newinode, full_path, NULL,						 inode->i_sb, xid);		if (pTcon->nocase)			direntry->d_op = &cifs_ci_dentry_ops;		else			direntry->d_op = &cifs_dentry_ops;		d_instantiate(direntry, newinode);		 /* setting nlink not necessary except in cases where we		  * failed to get it from the server or was set bogus */		if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))				direntry->d_inode->i_nlink = 2;		if (pTcon->unix_ext) {			mode &= ~current->fs->umask;			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {				CIFSSMBUnixSetPerms(xid, pTcon, full_path,						    mode,						    (__u64)current->fsuid,						    (__u64)current->fsgid,						    0 /* dev_t */,						    cifs_sb->local_nls,						    cifs_sb->mnt_cifs_flags &						    CIFS_MOUNT_MAP_SPECIAL_CHR);			} else {				CIFSSMBUnixSetPerms(xid, pTcon, full_path,						    mode, (__u64)-1,						    (__u64)-1, 0 /* dev_t */,						    cifs_sb->local_nls,						    cifs_sb->mnt_cifs_flags &						    CIFS_MOUNT_MAP_SPECIAL_CHR);			}		} else {			/* BB to be implemented via Windows secrty descriptors			   eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,						 -1, -1, local_nls); */			if (direntry->d_inode) {				direntry->d_inode->i_mode = mode;				direntry->d_inode->i_mode |= S_IFDIR;				if (cifs_sb->mnt_cifs_flags &				     CIFS_MOUNT_SET_UID) {					direntry->d_inode->i_uid =						current->fsuid;					direntry->d_inode->i_gid =						current->fsgid;				}			}		}	}mkdir_out:	kfree(full_path);	FreeXid(xid);	return rc;}int cifs_rmdir(struct inode *inode, struct dentry *direntry){	int rc = 0;	int xid;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	char *full_path = NULL;	struct cifsInodeInfo *cifsInode;	cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));	xid = GetXid();	cifs_sb = CIFS_SB(inode->i_sb);	pTcon = cifs_sb->tcon;	full_path = build_path_from_dentry(direntry);	if (full_path == NULL) {		FreeXid(xid);		return -ENOMEM;	}	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);	if (!rc) {		drop_nlink(inode);		spin_lock(&direntry->d_inode->i_lock);		i_size_write(direntry->d_inode, 0);		clear_nlink(direntry->d_inode);		spin_unlock(&direntry->d_inode->i_lock);	}	cifsInode = CIFS_I(direntry->d_inode);	cifsInode->time = 0;	/* force revalidate to go get info when				   needed */	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =		current_fs_time(inode->i_sb);	kfree(full_path);	FreeXid(xid);	return rc;}int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,	struct inode *target_inode, struct dentry *target_direntry){	char *fromName;	char *toName;	struct cifs_sb_info *cifs_sb_source;	struct cifs_sb_info *cifs_sb_target;	struct cifsTconInfo *pTcon;	int xid;	int rc = 0;	xid = GetXid();	cifs_sb_target = CIFS_SB(target_inode->i_sb);	cifs_sb_source = CIFS_SB(source_inode->i_sb);	pTcon = cifs_sb_source->tcon;	if (pTcon != cifs_sb_target->tcon) {		FreeXid(xid);		return -EXDEV;	/* BB actually could be allowed if same server,				   but different share.				   Might eventually add support for this */	}	/* we already  have the rename sem so we do not need to grab it again	   here to protect the path integrity */	fromName = build_path_from_dentry(source_direntry);	toName = build_path_from_dentry(target_direntry);	if ((fromName == NULL) || (toName == NULL)) {		rc = -ENOMEM;		goto cifs_rename_exit;	}	rc = CIFSSMBRename(xid, pTcon, fromName, toName,			   cifs_sb_source->local_nls,			   cifs_sb_source->mnt_cifs_flags &				CIFS_MOUNT_MAP_SPECIAL_CHR);	if (rc == -EEXIST) {		/* check if they are the same file because rename of hardlinked		   files is a noop */		FILE_UNIX_BASIC_INFO *info_buf_source;		FILE_UNIX_BASIC_INFO *info_buf_target;		info_buf_source =			kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);		if (info_buf_source != NULL) {			info_buf_target = info_buf_source + 1;			if (pTcon->unix_ext)				rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,					info_buf_source,					cifs_sb_source->local_nls,					cifs_sb_source->mnt_cifs_flags &						CIFS_MOUNT_MAP_SPECIAL_CHR);			/* else rc is still EEXIST so will fall through to			   unlink the target and retry rename */			if (rc == 0) {				rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,						info_buf_target,						cifs_sb_target->local_nls,						/* remap based on source sb */						cifs_sb_source->mnt_cifs_flags &						    CIFS_MOUNT_MAP_SPECIAL_CHR);			}			if ((rc == 0) &&			    (info_buf_source->UniqueId ==			     info_buf_target->UniqueId)) {			/* do not rename since the files are hardlinked which			   is a noop */			} else {			/* we either can not tell the files are hardlinked			   (as with Windows servers) or files are not			   hardlinked so delete the target manually before			   renaming to follow POSIX rather than Windows			   semantics */				cifs_unlink(target_inode, target_direntry);				rc = CIFSSMBRename(xid, pTcon, fromName,						   toName,						   cifs_sb_source->local_nls,						   cifs_sb_source->mnt_cifs_flags						   & CIFS_MOUNT_MAP_SPECIAL_CHR);			}			kfree(info_buf_source);		} /* if we can not get memory just leave rc as EEXIST */	}	if (rc) {		cFYI(1, ("rename rc %d", rc));	}	if ((rc == -EIO) || (rc == -EEXIST)) {		int oplock = FALSE;		__u16 netfid;		/* BB FIXME Is Generic Read correct for rename? */		/* if renaming directory - we should not say CREATE_NOT_DIR,		   need to test renaming open directory, also GENERIC_READ		   might not right be right access to request */		rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,				 CREATE_NOT_DIR, &netfid, &oplock, NULL,				 cifs_sb_source->local_nls,				 cifs_sb_source->mnt_cifs_flags &					CIFS_MOUNT_MAP_SPECIAL_CHR);		if (rc == 0) {			rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,					      cifs_sb_source->local_nls,					      cifs_sb_source->mnt_cifs_flags &						CIFS_MOUNT_MAP_SPECIAL_CHR);			CIFSSMBClose(xid, pTcon, netfid);		}	}cifs_rename_exit:	kfree(fromName);	kfree(toName);	FreeXid(xid);	return rc;}int cifs_revalidate(struct dentry *direntry){	int xid;	int rc = 0;	char *full_path;	struct cifs_sb_info *cifs_sb;	struct cifsInodeInfo *cifsInode;	loff_t local_size;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	struct timespec local_mtime;#else	time_t local_mtime;#endif	int invalidate_inode = FALSE;	if (direntry->d_inode == NULL)		return -ENOENT;	cifsInode = CIFS_I(direntry->d_inode);	if (cifsInode == NULL)		return -ENOENT;	/* no sense revalidating inode info on file that no one can write */	if (CIFS_I(direntry->d_inode)->clientCanCacheRead)		return rc;	xid = GetXid();	cifs_sb = CIFS_SB(direntry->d_sb);	/* can not safely grab the rename sem here if rename calls revalidate	   since that would deadlock */	full_path = build_path_from_dentry(direntry);	if (full_path == NULL) {		FreeXid(xid);		return -ENOMEM;	}	cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "		 "jiffies %ld", full_path, direntry->d_inode,		 direntry->d_inode->i_count.counter, direntry,		 direntry->d_time, jiffies));	if (cifsInode->time == 0) {		/* was set to zero previously to force revalidate */	} else if (time_before(jiffies, cifsInode->time + HZ) &&		   lookupCacheEnabled) {		if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||		    (direntry->d_inode->i_nlink == 1)) {			kfree(full_path);			FreeXid(xid);			return rc;		} else {			cFYI(1, ("Have to revalidate file due to hardlinks"));		}	}	/* save mtime and size */	local_mtime = direntry->d_inode->i_mtime;	local_size = direntry->d_inode->i_size;	if (cifs_sb->tcon->unix_ext) {		rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,					      direntry->d_sb, xid);		if (rc) {			cFYI(1, ("error on getting revalidate info %d", rc));/*			if (rc != -ENOENT)				rc = 0; */	/* BB should we cache info on						   certain errors? */		}

⌨️ 快捷键说明

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