📄 inode.c
字号:
(*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 + -