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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;			insert_inode_hash(*pinode);		}		inode = *pinode;		cifsInfo = CIFS_I(inode);		cifsInfo->cifsAttrs = attr;		cFYI(1, ("Old time %ld", cifsInfo->time));		cifsInfo->time = jiffies;		cFYI(1, ("New time %ld", cifsInfo->time));		/* blksize needs to be multiple of two. So safer to default to		blksize and blkbits set in superblock so 2**blkbits and blksize		will match rather than setting to:		(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/		/* Linux can not store file creation time so ignore it */		if (pfindData->LastAccessTime)			inode->i_atime = cifs_NTtimeToUnix				(le64_to_cpu(pfindData->LastAccessTime));		else /* do not need to use current_fs_time - time not stored */			inode->i_atime = CURRENT_TIME;		inode->i_mtime =		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));		inode->i_ctime =		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));		cFYI(0, ("Attributes came in as 0x%x", attr));		if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {			inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;			inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;		}		/* set default mode. will override for dirs below */		if (atomic_read(&cifsInfo->inUse) == 0)			/* new inode, can safely set these fields */			inode->i_mode = cifs_sb->mnt_file_mode;		else /* since we set the inode type below we need to mask off		     to avoid strange results if type changes and both		     get orred in */			inode->i_mode &= ~S_IFMT;/*		if (attr & ATTR_REPARSE)  */		/* We no longer handle these as symlinks because we could not		   follow them due to the absolute path with drive letter */		if (attr & ATTR_DIRECTORY) {		/* override default perms since we do not do byte range locking		   on dirs */			inode->i_mode = cifs_sb->mnt_dir_mode;			inode->i_mode |= S_IFDIR;		} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&			   (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&			   /* No need to le64 convert size of zero */			   (pfindData->EndOfFile == 0)) {			inode->i_mode = cifs_sb->mnt_file_mode;			inode->i_mode |= S_IFIFO;/* BB Finish for SFU style symlinks and devices */		} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&			   (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {			if (decode_sfu_inode(inode,					 le64_to_cpu(pfindData->EndOfFile),					 search_path,					 cifs_sb, xid)) {				cFYI(1, ("Unrecognized sfu inode type"));			}			cFYI(1, ("sfu mode 0%o", inode->i_mode));		} else {			inode->i_mode |= S_IFREG;			/* treat the dos attribute of read-only as read-only			   mode e.g. 555 */			if (cifsInfo->cifsAttrs & ATTR_READONLY)				inode->i_mode &= ~(S_IWUGO);			else if ((inode->i_mode & S_IWUGO) == 0)				/* the ATTR_READONLY flag may have been	*/				/* changed on server -- set any w bits	*/				/* allowed by mnt_file_mode		*/				inode->i_mode |= (S_IWUGO &						  cifs_sb->mnt_file_mode);		/* BB add code here -		   validate if device or weird share or device type? */		}		spin_lock(&inode->i_lock);		if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {			/* can not safely shrink the file size here if the			   client is writing to it due to potential races */			i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));			/* 512 bytes (2**9) is the fake blocksize that must be			   used for this calculation */			inode->i_blocks = (512 - 1 + le64_to_cpu(					   pfindData->AllocationSize)) >> 9;		}		spin_unlock(&inode->i_lock);		inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);		/* BB fill in uid and gid here? with help from winbind?		   or retrieve from NTFS stream extended attribute */#ifdef CONFIG_CIFS_EXPERIMENTAL		/* fill in 0777 bits from ACL */		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {			cFYI(1, ("Getting mode bits from ACL"));			acl_to_uid_mode(inode, search_path);		}#endif		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {			/* fill in remaining high mode bits e.g. SUID, VTX */			get_sfu_mode(inode, search_path, cifs_sb, xid);		} else if (atomic_read(&cifsInfo->inUse) == 0) {			inode->i_uid = cifs_sb->mnt_uid;			inode->i_gid = cifs_sb->mnt_gid;			/* set so we do not keep refreshing these fields with			   bad data after user has changed them in memory */			atomic_set(&cifsInfo->inUse, 1);		}		if (S_ISREG(inode->i_mode)) {			cFYI(1, ("File inode"));			inode->i_op = &cifs_file_inode_ops;			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {				if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)					inode->i_fop =						&cifs_file_direct_nobrl_ops;				else					inode->i_fop = &cifs_file_direct_ops;			} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)				inode->i_fop = &cifs_file_nobrl_ops;			else /* not direct, send byte range locks */				inode->i_fop = &cifs_file_ops;			if (pTcon->ses->server->maxBuf <			     PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)				inode->i_data.a_ops = &cifs_addr_ops_smallbuf;			else				inode->i_data.a_ops = &cifs_addr_ops;		} else if (S_ISDIR(inode->i_mode)) {			cFYI(1, ("Directory inode"));			inode->i_op = &cifs_dir_inode_ops;			inode->i_fop = &cifs_dir_ops;		} else if (S_ISLNK(inode->i_mode)) {			cFYI(1, ("Symbolic Link inode"));			inode->i_op = &cifs_symlink_inode_ops;		} else {			init_special_inode(inode, inode->i_mode,					   inode->i_rdev);		}	}	kfree(buf);	return rc;}static const struct inode_operations cifs_ipc_inode_ops = {	.lookup = cifs_lookup,};/* gets root inode */void cifs_read_inode(struct inode *inode){	int xid, rc;	struct cifs_sb_info *cifs_sb;	cifs_sb = CIFS_SB(inode->i_sb);	xid = GetXid();	if (cifs_sb->tcon->unix_ext)		rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);	else		rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);	if (rc && cifs_sb->tcon->ipc) {		cFYI(1, ("ipc connection - fake read inode"));		inode->i_mode |= S_IFDIR;		inode->i_nlink = 2;		inode->i_op = &cifs_ipc_inode_ops;		inode->i_fop = &simple_dir_operations;		inode->i_uid = cifs_sb->mnt_uid;		inode->i_gid = cifs_sb->mnt_gid;	}	/* can not call macro FreeXid here since in a void func */	_FreeXid(xid);}int cifs_unlink(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;	FILE_BASIC_INFO *pinfo_buf;	cFYI(1, ("cifs_unlink, inode = 0x%p", inode));	xid = GetXid();	if (inode)		cifs_sb = CIFS_SB(inode->i_sb);	else		cifs_sb = CIFS_SB(direntry->d_sb);	pTcon = cifs_sb->tcon;	/* Unlink can be called from rename so we can not grab the sem here	   since we deadlock otherwise *//*	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);*/	full_path = build_path_from_dentry(direntry);/*	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);*/	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))) {		rc = CIFSPOSIXDelFile(xid, pTcon, full_path,			SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);		cFYI(1, ("posix del rc %d", rc));		if ((rc == 0) || (rc == -ENOENT))			goto psx_del_no_retry;	}	rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);psx_del_no_retry:	if (!rc) {		if (direntry->d_inode)			drop_nlink(direntry->d_inode);	} else if (rc == -ENOENT) {		d_drop(direntry);	} else if (rc == -ETXTBSY) {		int oplock = FALSE;		__u16 netfid;		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,				 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,				 &netfid, &oplock, NULL, cifs_sb->local_nls,				 cifs_sb->mnt_cifs_flags &					CIFS_MOUNT_MAP_SPECIAL_CHR);		if (rc == 0) {			CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,					      cifs_sb->local_nls,					      cifs_sb->mnt_cifs_flags &						CIFS_MOUNT_MAP_SPECIAL_CHR);			CIFSSMBClose(xid, pTcon, netfid);			if (direntry->d_inode)				drop_nlink(direntry->d_inode);		}	} else if (rc == -EACCES) {		/* try only if r/o attribute set in local lookup data? */		pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);		if (pinfo_buf) {			/* ATTRS set to normal clears r/o bit */			pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);			if (!(pTcon->ses->flags & CIFS_SES_NT4))				rc = CIFSSMBSetTimes(xid, pTcon, full_path,						     pinfo_buf,						     cifs_sb->local_nls,						     cifs_sb->mnt_cifs_flags &							CIFS_MOUNT_MAP_SPECIAL_CHR);			else				rc = -EOPNOTSUPP;			if (rc == -EOPNOTSUPP) {				int oplock = FALSE;				__u16 netfid;			/*	rc = CIFSSMBSetAttrLegacy(xid, pTcon,							  full_path,							  (__u16)ATTR_NORMAL,							  cifs_sb->local_nls);			   For some strange reason it seems that NT4 eats the			   old setattr call without actually setting the			   attributes so on to the third attempted workaround			   */			/* BB could scan to see if we already have it open			   and pass in pid of opener to function */				rc = CIFSSMBOpen(xid, pTcon, full_path,						 FILE_OPEN, SYNCHRONIZE |						 FILE_WRITE_ATTRIBUTES, 0,						 &netfid, &oplock, NULL,						 cifs_sb->local_nls,						 cifs_sb->mnt_cifs_flags &						    CIFS_MOUNT_MAP_SPECIAL_CHR);				if (rc == 0) {					rc = CIFSSMBSetFileTimes(xid, pTcon,								 pinfo_buf,								 netfid);					CIFSSMBClose(xid, pTcon, netfid);				}			}			kfree(pinfo_buf);		}		if (rc == 0) {			rc = CIFSSMBDelFile(xid, pTcon, full_path,					    cifs_sb->local_nls,					    cifs_sb->mnt_cifs_flags &						CIFS_MOUNT_MAP_SPECIAL_CHR);			if (!rc) {				if (direntry->d_inode)					drop_nlink(direntry->d_inode);			} else if (rc == -ETXTBSY) {				int oplock = FALSE;				__u16 netfid;				rc = CIFSSMBOpen(xid, pTcon, full_path,						 FILE_OPEN, DELETE,						 CREATE_NOT_DIR |						 CREATE_DELETE_ON_CLOSE,						 &netfid, &oplock, NULL,						 cifs_sb->local_nls,						 cifs_sb->mnt_cifs_flags &						    CIFS_MOUNT_MAP_SPECIAL_CHR);				if (rc == 0) {					CIFSSMBRenameOpenFile(xid, pTcon,						netfid, NULL,						cifs_sb->local_nls,						cifs_sb->mnt_cifs_flags &						    CIFS_MOUNT_MAP_SPECIAL_CHR);					CIFSSMBClose(xid, pTcon, netfid);					if (direntry->d_inode)						drop_nlink(direntry->d_inode);				}			/* BB if rc = -ETXTBUSY goto the rename logic BB */			}		}	}	if (direntry->d_inode) {		cifsInode = CIFS_I(direntry->d_inode);		cifsInode->time = 0;	/* will force revalidate to get info					   when needed */		direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);	}	if (inode) {		inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);		cifsInode = CIFS_I(inode);		cifsInode->time = 0;	/* force revalidate of dir as well */	}	kfree(full_path);	FreeXid(xid);	return rc;}static void posix_fill_in_inode(struct inode *tmp_inode,	FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode){	loff_t local_size;	struct timespec local_mtime;	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);	__u32 type = le32_to_cpu(pData->Type);	__u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes);	__u64 end_of_file = le64_to_cpu(pData->EndOfFile);	cifsInfo->time = jiffies;	atomic_inc(&cifsInfo->inUse);	/* save mtime and size */	local_mtime = tmp_inode->i_mtime;	local_size  = tmp_inode->i_size;	tmp_inode->i_atime =	    cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));	tmp_inode->i_mtime =	    cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime));	tmp_inode->i_ctime =	    cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange));	tmp_inode->i_mode = le64_to_cpu(pData->Permissions);	/* since we set the inode type below we need to mask off type	   to avoid strange results if bits above were corrupt */	tmp_inode->i_mode &= ~S_IFMT;	if (type == UNIX_FILE) {		*pobject_type = DT_REG;		tmp_inode->i_mode |= S_IFREG;	} else if (type == UNIX_SYMLINK) {		*pobject_type = DT_LNK;		tmp_inode->i_mode |= S_IFLNK;	} else if (type == UNIX_DIR) {		*pobject_type = DT_DIR;		tmp_inode->i_mode |= S_IFDIR;	} else if (type == UNIX_CHARDEV) {		*pobject_type = DT_CHR;		tmp_inode->i_mode |= S_IFCHR;		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),				le64_to_cpu(pData->DevMinor) & MINORMASK);	} else if (type == UNIX_BLOCKDEV) {		*pobject_type = DT_BLK;		tmp_inode->i_mode |= S_IFBLK;		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),				le64_to_cpu(pData->DevMinor) & MINORMASK);	} else if (type == UNIX_FIFO) {		*pobject_type = DT_FIFO;		tmp_inode->i_mode |= S_IFIFO;	} else if (type == UNIX_SOCKET) {		*pobject_type = DT_SOCK;		tmp_inode->i_mode |= S_IFSOCK;	} else {		/* safest to just call it a file */		*pobject_type = DT_REG;		tmp_inode->i_mode |= S_IFREG;		cFYI(1, ("unknown inode type %d", type));	}#ifdef CONFIG_CIFS_DEBUG2	cFYI(1, ("object type: %d", type));#endif	tmp_inode->i_uid = le64_to_cpu(pData->Uid);	tmp_inode->i_gid = le64_to_cpu(pData->Gid);	tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks);	spin_lock(&tmp_inode->i_lock);	if (is_size_safe_to_change(cifsInfo, end_of_file)) {		/* can not safely change the file size here if the		client is writing to it due to potential races */		i_size_write(tmp_inode, end_of_file);	/* 512 bytes (2**9) is the fake blocksize that must be used */	/* for this calculation, not the real blocksize */		tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;	}	spin_unlock(&tmp_inode->i_lock);	if (S_ISREG(tmp_inode->i_mode)) {		cFYI(1, ("File inode"));		tmp_inode->i_op = &cifs_file_inode_ops;		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)				tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;			else				tmp_inode->i_fop = &cifs_file_direct_ops;

⌨️ 快捷键说明

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