diff options
| -rw-r--r-- | fs/cifs/cifsfs.h | 13 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 25 | ||||
| -rw-r--r-- | fs/cifs/cifspdu.h | 14 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 9 | ||||
| -rw-r--r-- | fs/cifs/dir.c | 22 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 380 | ||||
| -rw-r--r-- | fs/cifs/readdir.c | 253 |
7 files changed, 339 insertions, 377 deletions
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 9570a0e8023f..586df24c9abb 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -24,6 +24,19 @@ | |||
| 24 | 24 | ||
| 25 | #define ROOT_I 2 | 25 | #define ROOT_I 2 |
| 26 | 26 | ||
| 27 | /* | ||
| 28 | * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down | ||
| 29 | * so that it will fit. | ||
| 30 | */ | ||
| 31 | static inline ino_t | ||
| 32 | cifs_uniqueid_to_ino_t(u64 fileid) | ||
| 33 | { | ||
| 34 | ino_t ino = (ino_t) fileid; | ||
| 35 | if (sizeof(ino_t) < sizeof(u64)) | ||
| 36 | ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; | ||
| 37 | return ino; | ||
| 38 | } | ||
| 39 | |||
| 27 | extern struct file_system_type cifs_fs_type; | 40 | extern struct file_system_type cifs_fs_type; |
| 28 | extern const struct address_space_operations cifs_addr_ops; | 41 | extern const struct address_space_operations cifs_addr_ops; |
| 29 | extern const struct address_space_operations cifs_addr_ops_smallbuf; | 42 | extern const struct address_space_operations cifs_addr_ops_smallbuf; |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e1225e6ded2f..e6435cba8113 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -371,6 +371,7 @@ struct cifsInodeInfo { | |||
| 371 | bool oplockPending:1; | 371 | bool oplockPending:1; |
| 372 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ | 372 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ |
| 373 | u64 server_eof; /* current file size on server */ | 373 | u64 server_eof; /* current file size on server */ |
| 374 | u64 uniqueid; /* server inode number */ | ||
| 374 | struct inode vfs_inode; | 375 | struct inode vfs_inode; |
| 375 | }; | 376 | }; |
| 376 | 377 | ||
| @@ -472,6 +473,30 @@ struct dfs_info3_param { | |||
| 472 | char *node_name; | 473 | char *node_name; |
| 473 | }; | 474 | }; |
| 474 | 475 | ||
| 476 | /* | ||
| 477 | * common struct for holding inode info when searching for or updating an | ||
| 478 | * inode with new info | ||
| 479 | */ | ||
| 480 | |||
| 481 | #define CIFS_FATTR_DFS_REFERRAL 0x1 | ||
| 482 | |||
| 483 | struct cifs_fattr { | ||
| 484 | u32 cf_flags; | ||
| 485 | u32 cf_cifsattrs; | ||
| 486 | u64 cf_uniqueid; | ||
| 487 | u64 cf_eof; | ||
| 488 | u64 cf_bytes; | ||
| 489 | uid_t cf_uid; | ||
| 490 | gid_t cf_gid; | ||
| 491 | umode_t cf_mode; | ||
| 492 | dev_t cf_rdev; | ||
| 493 | unsigned int cf_nlink; | ||
| 494 | unsigned int cf_dtype; | ||
| 495 | struct timespec cf_atime; | ||
| 496 | struct timespec cf_mtime; | ||
| 497 | struct timespec cf_ctime; | ||
| 498 | }; | ||
| 499 | |||
| 475 | static inline void free_dfs_info_param(struct dfs_info3_param *param) | 500 | static inline void free_dfs_info_param(struct dfs_info3_param *param) |
| 476 | { | 501 | { |
| 477 | if (param) { | 502 | if (param) { |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index a785f69dbc9f..2d07f890a842 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -2328,19 +2328,7 @@ struct file_attrib_tag { | |||
| 2328 | typedef struct { | 2328 | typedef struct { |
| 2329 | __le32 NextEntryOffset; | 2329 | __le32 NextEntryOffset; |
| 2330 | __u32 ResumeKey; /* as with FileIndex - no need to convert */ | 2330 | __u32 ResumeKey; /* as with FileIndex - no need to convert */ |
| 2331 | __le64 EndOfFile; | 2331 | FILE_UNIX_BASIC_INFO basic; |
| 2332 | __le64 NumOfBytes; | ||
| 2333 | __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ | ||
| 2334 | __le64 LastAccessTime; | ||
| 2335 | __le64 LastModificationTime; | ||
| 2336 | __le64 Uid; | ||
| 2337 | __le64 Gid; | ||
| 2338 | __le32 Type; | ||
| 2339 | __le64 DevMajor; | ||
| 2340 | __le64 DevMinor; | ||
| 2341 | __le64 UniqueId; | ||
| 2342 | __le64 Permissions; | ||
| 2343 | __le64 Nlinks; | ||
| 2344 | char FileName[1]; | 2332 | char FileName[1]; |
| 2345 | } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ | 2333 | } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ |
| 2346 | 2334 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c419416a42ee..b2bd83fd2aa4 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -98,9 +98,14 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, | |||
| 98 | extern int cifs_posix_open(char *full_path, struct inode **pinode, | 98 | extern int cifs_posix_open(char *full_path, struct inode **pinode, |
| 99 | struct super_block *sb, int mode, int oflags, | 99 | struct super_block *sb, int mode, int oflags, |
| 100 | int *poplock, __u16 *pnetfid, int xid); | 100 | int *poplock, __u16 *pnetfid, int xid); |
| 101 | extern void posix_fill_in_inode(struct inode *tmp_inode, | 101 | extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, |
| 102 | FILE_UNIX_BASIC_INFO *pData, int isNewInode); | 102 | FILE_UNIX_BASIC_INFO *info, |
| 103 | struct cifs_sb_info *cifs_sb); | ||
| 104 | extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); | ||
| 103 | extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); | 105 | extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); |
| 106 | extern struct inode *cifs_iget(struct super_block *sb, | ||
| 107 | struct cifs_fattr *fattr); | ||
| 108 | |||
| 104 | extern int cifs_get_inode_info(struct inode **pinode, | 109 | extern int cifs_get_inode_info(struct inode **pinode, |
| 105 | const unsigned char *search_path, | 110 | const unsigned char *search_path, |
| 106 | FILE_ALL_INFO *pfile_info, | 111 | FILE_ALL_INFO *pfile_info, |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7dc6b74f9def..a40054faed7f 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
| 188 | FILE_UNIX_BASIC_INFO *presp_data; | 188 | FILE_UNIX_BASIC_INFO *presp_data; |
| 189 | __u32 posix_flags = 0; | 189 | __u32 posix_flags = 0; |
| 190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 191 | struct cifs_fattr fattr; | ||
| 191 | 192 | ||
| 192 | cFYI(1, ("posix open %s", full_path)); | 193 | cFYI(1, ("posix open %s", full_path)); |
| 193 | 194 | ||
| @@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
| 236 | if (presp_data->Type == cpu_to_le32(-1)) | 237 | if (presp_data->Type == cpu_to_le32(-1)) |
| 237 | goto posix_open_ret; /* open ok, caller does qpathinfo */ | 238 | goto posix_open_ret; /* open ok, caller does qpathinfo */ |
| 238 | 239 | ||
| 239 | /* get new inode and set it up */ | ||
| 240 | if (!pinode) | 240 | if (!pinode) |
| 241 | goto posix_open_ret; /* caller does not need info */ | 241 | goto posix_open_ret; /* caller does not need info */ |
| 242 | 242 | ||
| 243 | cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); | ||
| 244 | |||
| 245 | /* get new inode and set it up */ | ||
| 243 | if (*pinode == NULL) { | 246 | if (*pinode == NULL) { |
| 244 | __u64 unique_id = le64_to_cpu(presp_data->UniqueId); | 247 | *pinode = cifs_iget(sb, &fattr); |
| 245 | *pinode = cifs_new_inode(sb, &unique_id); | 248 | if (!*pinode) { |
| 249 | rc = -ENOMEM; | ||
| 250 | goto posix_open_ret; | ||
| 251 | } | ||
| 252 | } else { | ||
| 253 | cifs_fattr_to_inode(*pinode, &fattr); | ||
| 246 | } | 254 | } |
| 247 | /* else an inode was passed in. Update its info, don't create one */ | ||
| 248 | |||
| 249 | /* We do not need to close the file if new_inode fails since | ||
| 250 | the caller will retry qpathinfo as long as inode is null */ | ||
| 251 | if (*pinode == NULL) | ||
| 252 | goto posix_open_ret; | ||
| 253 | |||
| 254 | posix_fill_in_inode(*pinode, presp_data, 1); | ||
| 255 | 255 | ||
| 256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); | 256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); |
| 257 | 257 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 155c9e785d0c..b22379610d71 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -77,127 +77,146 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
| 77 | } | 77 | } |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static void cifs_unix_info_to_inode(struct inode *inode, | 80 | /* populate an inode with info from a cifs_fattr struct */ |
| 81 | FILE_UNIX_BASIC_INFO *info, int force_uid_gid) | 81 | void |
| 82 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | ||
| 82 | { | 83 | { |
| 83 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 84 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
| 84 | struct cifsInodeInfo *cifsInfo = CIFS_I(inode); | 85 | unsigned long now = jiffies; |
| 85 | __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); | 86 | |
| 86 | __u64 end_of_file = le64_to_cpu(info->EndOfFile); | 87 | inode->i_atime = fattr->cf_atime; |
| 88 | inode->i_mtime = fattr->cf_mtime; | ||
| 89 | inode->i_ctime = fattr->cf_ctime; | ||
| 90 | inode->i_mode = fattr->cf_mode; | ||
| 91 | inode->i_rdev = fattr->cf_rdev; | ||
| 92 | inode->i_nlink = fattr->cf_nlink; | ||
| 93 | inode->i_uid = fattr->cf_uid; | ||
| 94 | inode->i_gid = fattr->cf_gid; | ||
| 95 | |||
| 96 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; | ||
| 97 | cifs_i->uniqueid = fattr->cf_uniqueid; | ||
| 98 | |||
| 99 | cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, | ||
| 100 | cifs_i->time, now)); | ||
| 101 | cifs_i->time = now; | ||
| 102 | |||
| 103 | /* | ||
| 104 | * Can't safely change the file size here if the client is writing to | ||
| 105 | * it due to potential races. | ||
| 106 | */ | ||
| 107 | spin_lock(&inode->i_lock); | ||
| 108 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { | ||
| 109 | i_size_write(inode, fattr->cf_eof); | ||
| 110 | |||
| 111 | /* | ||
| 112 | * i_blocks is not related to (i_size / i_blksize), | ||
| 113 | * but instead 512 byte (2**9) size is required for | ||
| 114 | * calculating num blocks. | ||
| 115 | */ | ||
| 116 | inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; | ||
| 117 | } | ||
| 118 | spin_unlock(&inode->i_lock); | ||
| 119 | |||
| 120 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ | ||
| 124 | void | ||
| 125 | cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, | ||
| 126 | struct cifs_sb_info *cifs_sb) | ||
| 127 | { | ||
| 128 | memset(fattr, 0, sizeof(*fattr)); | ||
| 129 | fattr->cf_uniqueid = le64_to_cpu(info->UniqueId); | ||
| 130 | fattr->cf_bytes = le64_to_cpu(info->NumOfBytes); | ||
| 131 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | ||
| 87 | 132 | ||
| 88 | inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime); | 133 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
| 89 | inode->i_mtime = | 134 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); |
| 90 | cifs_NTtimeToUnix(info->LastModificationTime); | 135 | fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); |
| 91 | inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange); | 136 | fattr->cf_mode = le64_to_cpu(info->Permissions); |
| 92 | inode->i_mode = le64_to_cpu(info->Permissions); | ||
| 93 | 137 | ||
| 94 | /* | 138 | /* |
| 95 | * Since we set the inode type below we need to mask off | 139 | * Since we set the inode type below we need to mask off |
| 96 | * to avoid strange results if bits set above. | 140 | * to avoid strange results if bits set above. |
| 97 | */ | 141 | */ |
| 98 | inode->i_mode &= ~S_IFMT; | 142 | fattr->cf_mode &= ~S_IFMT; |
| 99 | switch (le32_to_cpu(info->Type)) { | 143 | switch (le32_to_cpu(info->Type)) { |
| 100 | case UNIX_FILE: | 144 | case UNIX_FILE: |
| 101 | inode->i_mode |= S_IFREG; | 145 | fattr->cf_mode |= S_IFREG; |
| 146 | fattr->cf_dtype = DT_REG; | ||
| 102 | break; | 147 | break; |
| 103 | case UNIX_SYMLINK: | 148 | case UNIX_SYMLINK: |
| 104 | inode->i_mode |= S_IFLNK; | 149 | fattr->cf_mode |= S_IFLNK; |
| 150 | fattr->cf_dtype = DT_LNK; | ||
| 105 | break; | 151 | break; |
| 106 | case UNIX_DIR: | 152 | case UNIX_DIR: |
| 107 | inode->i_mode |= S_IFDIR; | 153 | fattr->cf_mode |= S_IFDIR; |
| 154 | fattr->cf_dtype = DT_DIR; | ||
| 108 | break; | 155 | break; |
| 109 | case UNIX_CHARDEV: | 156 | case UNIX_CHARDEV: |
| 110 | inode->i_mode |= S_IFCHR; | 157 | fattr->cf_mode |= S_IFCHR; |
| 111 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 158 | fattr->cf_dtype = DT_CHR; |
| 112 | le64_to_cpu(info->DevMinor) & MINORMASK); | 159 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
| 160 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
| 113 | break; | 161 | break; |
| 114 | case UNIX_BLOCKDEV: | 162 | case UNIX_BLOCKDEV: |
| 115 | inode->i_mode |= S_IFBLK; | 163 | fattr->cf_mode |= S_IFBLK; |
| 116 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 164 | fattr->cf_dtype = DT_BLK; |
| 117 | le64_to_cpu(info->DevMinor) & MINORMASK); | 165 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
| 166 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
| 118 | break; | 167 | break; |
| 119 | case UNIX_FIFO: | 168 | case UNIX_FIFO: |
| 120 | inode->i_mode |= S_IFIFO; | 169 | fattr->cf_mode |= S_IFIFO; |
| 170 | fattr->cf_dtype = DT_FIFO; | ||
| 121 | break; | 171 | break; |
| 122 | case UNIX_SOCKET: | 172 | case UNIX_SOCKET: |
| 123 | inode->i_mode |= S_IFSOCK; | 173 | fattr->cf_mode |= S_IFSOCK; |
| 174 | fattr->cf_dtype = DT_SOCK; | ||
| 124 | break; | 175 | break; |
| 125 | default: | 176 | default: |
| 126 | /* safest to call it a file if we do not know */ | 177 | /* safest to call it a file if we do not know */ |
| 127 | inode->i_mode |= S_IFREG; | 178 | fattr->cf_mode |= S_IFREG; |
| 179 | fattr->cf_dtype = DT_REG; | ||
| 128 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); | 180 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); |
| 129 | break; | 181 | break; |
| 130 | } | 182 | } |
| 131 | 183 | ||
| 132 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && | 184 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
| 133 | !force_uid_gid) | 185 | fattr->cf_uid = cifs_sb->mnt_uid; |
| 134 | inode->i_uid = cifs_sb->mnt_uid; | ||
| 135 | else | 186 | else |
| 136 | inode->i_uid = le64_to_cpu(info->Uid); | 187 | fattr->cf_uid = le64_to_cpu(info->Uid); |
| 137 | 188 | ||
| 138 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && | 189 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
| 139 | !force_uid_gid) | 190 | fattr->cf_gid = cifs_sb->mnt_gid; |
| 140 | inode->i_gid = cifs_sb->mnt_gid; | ||
| 141 | else | 191 | else |
| 142 | inode->i_gid = le64_to_cpu(info->Gid); | 192 | fattr->cf_gid = le64_to_cpu(info->Gid); |
| 143 | 193 | ||
| 144 | inode->i_nlink = le64_to_cpu(info->Nlinks); | 194 | fattr->cf_nlink = le64_to_cpu(info->Nlinks); |
| 145 | |||
| 146 | cifsInfo->server_eof = end_of_file; | ||
| 147 | spin_lock(&inode->i_lock); | ||
| 148 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
| 149 | /* | ||
| 150 | * We can not safely change the file size here if the client | ||
| 151 | * is writing to it due to potential races. | ||
| 152 | */ | ||
| 153 | i_size_write(inode, end_of_file); | ||
| 154 | |||
| 155 | /* | ||
| 156 | * i_blocks is not related to (i_size / i_blksize), | ||
| 157 | * but instead 512 byte (2**9) size is required for | ||
| 158 | * calculating num blocks. | ||
| 159 | */ | ||
| 160 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
| 161 | } | ||
| 162 | spin_unlock(&inode->i_lock); | ||
| 163 | } | 195 | } |
| 164 | 196 | ||
| 165 | |||
| 166 | /* | 197 | /* |
| 167 | * Needed to setup inode data for the directory which is the | 198 | * Fill a cifs_fattr struct with fake inode info. |
| 168 | * junction to the new submount (ie to setup the fake directory | 199 | * |
| 169 | * which represents a DFS referral) | 200 | * Needed to setup cifs_fattr data for the directory which is the |
| 201 | * junction to the new submount (ie to setup the fake directory | ||
| 202 | * which represents a DFS referral). | ||
| 170 | */ | 203 | */ |
| 171 | static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, | 204 | void |
| 172 | struct super_block *sb) | 205 | cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) |
| 173 | { | 206 | { |
| 174 | struct inode *pinode = NULL; | 207 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 175 | |||
| 176 | memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); | ||
| 177 | 208 | ||
| 178 | /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | 209 | cFYI(1, ("creating fake fattr for DFS referral")); |
| 179 | __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); | 210 | |
| 180 | __u64 UniqueId = 0; */ | 211 | memset(fattr, 0, sizeof(*fattr)); |
| 181 | pfnd_dat->LastStatusChange = | 212 | fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; |
| 182 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 213 | fattr->cf_uid = cifs_sb->mnt_uid; |
| 183 | pfnd_dat->LastAccessTime = | 214 | fattr->cf_gid = cifs_sb->mnt_gid; |
| 184 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 215 | fattr->cf_atime = CURRENT_TIME; |
| 185 | pfnd_dat->LastModificationTime = | 216 | fattr->cf_ctime = CURRENT_TIME; |
| 186 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 217 | fattr->cf_mtime = CURRENT_TIME; |
| 187 | pfnd_dat->Type = cpu_to_le32(UNIX_DIR); | 218 | fattr->cf_nlink = 2; |
| 188 | pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); | 219 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; |
| 189 | pfnd_dat->Nlinks = cpu_to_le64(2); | ||
| 190 | if (sb->s_root) | ||
| 191 | pinode = sb->s_root->d_inode; | ||
| 192 | if (pinode == NULL) | ||
| 193 | return; | ||
| 194 | |||
| 195 | /* fill in default values for the remaining based on root | ||
| 196 | inode since we can not query the server for this inode info */ | ||
| 197 | pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); | ||
| 198 | pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); | ||
| 199 | pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); | ||
| 200 | pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); | ||
| 201 | } | 220 | } |
| 202 | 221 | ||
| 203 | /** | 222 | /** |
| @@ -244,66 +263,42 @@ cifs_new_inode(struct super_block *sb, __u64 *inum) | |||
| 244 | } | 263 | } |
| 245 | 264 | ||
| 246 | int cifs_get_inode_info_unix(struct inode **pinode, | 265 | int cifs_get_inode_info_unix(struct inode **pinode, |
| 247 | const unsigned char *full_path, struct super_block *sb, int xid) | 266 | const unsigned char *full_path, |
| 267 | struct super_block *sb, int xid) | ||
| 248 | { | 268 | { |
| 249 | int rc = 0; | 269 | int rc; |
| 250 | FILE_UNIX_BASIC_INFO find_data; | 270 | FILE_UNIX_BASIC_INFO find_data; |
| 251 | struct cifsTconInfo *pTcon; | 271 | struct cifs_fattr fattr; |
| 252 | struct inode *inode; | 272 | struct cifsTconInfo *tcon; |
| 253 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 273 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 254 | bool is_dfs_referral = false; | ||
| 255 | struct cifsInodeInfo *cifsInfo; | ||
| 256 | __u64 num_of_bytes; | ||
| 257 | __u64 end_of_file; | ||
| 258 | 274 | ||
| 259 | pTcon = cifs_sb->tcon; | 275 | tcon = cifs_sb->tcon; |
| 260 | cFYI(1, ("Getting info on %s", full_path)); | 276 | cFYI(1, ("Getting info on %s", full_path)); |
| 261 | 277 | ||
| 262 | /* could have done a find first instead but this returns more info */ | 278 | /* could have done a find first instead but this returns more info */ |
| 263 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, | 279 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
| 264 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 280 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
| 265 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 281 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 266 | if (rc == -EREMOTE && !is_dfs_referral) { | ||
| 267 | is_dfs_referral = true; | ||
| 268 | cFYI(DBG2, ("DFS ref")); | ||
| 269 | /* for DFS, server does not give us real inode data */ | ||
| 270 | fill_fake_finddataunix(&find_data, sb); | ||
| 271 | rc = 0; | ||
| 272 | } else if (rc) | ||
| 273 | goto cgiiu_exit; | ||
| 274 | 282 | ||
| 275 | num_of_bytes = le64_to_cpu(find_data.NumOfBytes); | 283 | if (!rc) { |
| 276 | end_of_file = le64_to_cpu(find_data.EndOfFile); | 284 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
| 285 | } else if (rc == -EREMOTE) { | ||
| 286 | cifs_create_dfs_fattr(&fattr, sb); | ||
| 287 | rc = 0; | ||
| 288 | } else { | ||
| 289 | return rc; | ||
| 290 | } | ||
| 277 | 291 | ||
| 278 | /* get new inode */ | ||
| 279 | if (*pinode == NULL) { | 292 | if (*pinode == NULL) { |
| 280 | __u64 unique_id = le64_to_cpu(find_data.UniqueId); | 293 | /* get new inode */ |
| 281 | *pinode = cifs_new_inode(sb, &unique_id); | 294 | *pinode = cifs_iget(sb, &fattr); |
| 282 | if (*pinode == NULL) { | 295 | if (!*pinode) |
| 283 | rc = -ENOMEM; | 296 | rc = -ENOMEM; |
| 284 | goto cgiiu_exit; | 297 | } else { |
| 285 | } | 298 | /* we already have inode, update it */ |
| 299 | cifs_fattr_to_inode(*pinode, &fattr); | ||
| 286 | } | 300 | } |
| 287 | 301 | ||
| 288 | inode = *pinode; | ||
| 289 | cifsInfo = CIFS_I(inode); | ||
| 290 | |||
| 291 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
| 292 | cifsInfo->time = jiffies; | ||
| 293 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
| 294 | /* this is ok to set on every inode revalidate */ | ||
| 295 | atomic_set(&cifsInfo->inUse, 1); | ||
| 296 | |||
| 297 | cifs_unix_info_to_inode(inode, &find_data, 0); | ||
| 298 | |||
| 299 | if (num_of_bytes < end_of_file) | ||
| 300 | cFYI(1, ("allocation size less than end of file")); | ||
| 301 | cFYI(1, ("Size %ld and blocks %llu", | ||
| 302 | (unsigned long) inode->i_size, | ||
| 303 | (unsigned long long)inode->i_blocks)); | ||
| 304 | |||
| 305 | cifs_set_ops(inode, is_dfs_referral); | ||
| 306 | cgiiu_exit: | ||
| 307 | return rc; | 302 | return rc; |
| 308 | } | 303 | } |
| 309 | 304 | ||
| @@ -695,33 +690,85 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
| 695 | return full_path; | 690 | return full_path; |
| 696 | } | 691 | } |
| 697 | 692 | ||
| 693 | static int | ||
| 694 | cifs_find_inode(struct inode *inode, void *opaque) | ||
| 695 | { | ||
| 696 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
| 697 | |||
| 698 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | ||
| 699 | return 0; | ||
| 700 | |||
| 701 | return 1; | ||
| 702 | } | ||
| 703 | |||
| 704 | static int | ||
| 705 | cifs_init_inode(struct inode *inode, void *opaque) | ||
| 706 | { | ||
| 707 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
| 708 | |||
| 709 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; | ||
| 710 | return 0; | ||
| 711 | } | ||
| 712 | |||
| 713 | /* Given fattrs, get a corresponding inode */ | ||
| 714 | struct inode * | ||
| 715 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | ||
| 716 | { | ||
| 717 | unsigned long hash; | ||
| 718 | struct inode *inode; | ||
| 719 | |||
| 720 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); | ||
| 721 | |||
| 722 | /* hash down to 32-bits on 32-bit arch */ | ||
| 723 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); | ||
| 724 | |||
| 725 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | ||
| 726 | |||
| 727 | /* we have fattrs in hand, update the inode */ | ||
| 728 | if (inode) { | ||
| 729 | cifs_fattr_to_inode(inode, fattr); | ||
| 730 | if (sb->s_flags & MS_NOATIME) | ||
| 731 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
| 732 | if (inode->i_state & I_NEW) { | ||
| 733 | inode->i_ino = hash; | ||
| 734 | unlock_new_inode(inode); | ||
| 735 | } | ||
| 736 | } | ||
| 737 | |||
| 738 | return inode; | ||
| 739 | } | ||
| 740 | |||
| 698 | /* gets root inode */ | 741 | /* gets root inode */ |
| 699 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 742 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) |
| 700 | { | 743 | { |
| 701 | int xid; | 744 | int xid; |
| 702 | struct cifs_sb_info *cifs_sb; | 745 | struct cifs_sb_info *cifs_sb; |
| 703 | struct inode *inode; | 746 | struct inode *inode = NULL; |
| 704 | long rc; | 747 | long rc; |
| 705 | char *full_path; | 748 | char *full_path; |
| 706 | 749 | ||
| 707 | inode = iget_locked(sb, ino); | 750 | cifs_sb = CIFS_SB(sb); |
| 708 | if (!inode) | ||
| 709 | return ERR_PTR(-ENOMEM); | ||
| 710 | if (!(inode->i_state & I_NEW)) | ||
| 711 | return inode; | ||
| 712 | |||
| 713 | cifs_sb = CIFS_SB(inode->i_sb); | ||
| 714 | full_path = cifs_build_path_to_root(cifs_sb); | 751 | full_path = cifs_build_path_to_root(cifs_sb); |
| 715 | if (full_path == NULL) | 752 | if (full_path == NULL) |
| 716 | return ERR_PTR(-ENOMEM); | 753 | return ERR_PTR(-ENOMEM); |
| 717 | 754 | ||
| 718 | xid = GetXid(); | 755 | xid = GetXid(); |
| 719 | if (cifs_sb->tcon->unix_ext) | 756 | if (cifs_sb->tcon->unix_ext) { |
| 720 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, | 757 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
| 721 | xid); | 758 | if (!inode) |
| 722 | else | 759 | return ERR_PTR(-ENOMEM); |
| 760 | } else { | ||
| 761 | inode = iget_locked(sb, ino); | ||
| 762 | if (!inode) | ||
| 763 | return ERR_PTR(-ENOMEM); | ||
| 764 | if (!(inode->i_state & I_NEW)) | ||
| 765 | return inode; | ||
| 766 | |||
| 723 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, | 767 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, |
| 724 | xid, NULL); | 768 | xid, NULL); |
| 769 | unlock_new_inode(inode); | ||
| 770 | } | ||
| 771 | |||
| 725 | if (rc && cifs_sb->tcon->ipc) { | 772 | if (rc && cifs_sb->tcon->ipc) { |
| 726 | cFYI(1, ("ipc connection - fake read inode")); | 773 | cFYI(1, ("ipc connection - fake read inode")); |
| 727 | inode->i_mode |= S_IFDIR; | 774 | inode->i_mode |= S_IFDIR; |
| @@ -737,7 +784,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
| 737 | return ERR_PTR(rc); | 784 | return ERR_PTR(rc); |
| 738 | } | 785 | } |
| 739 | 786 | ||
| 740 | unlock_new_inode(inode); | ||
| 741 | 787 | ||
| 742 | kfree(full_path); | 788 | kfree(full_path); |
| 743 | /* can not call macro FreeXid here since in a void func | 789 | /* can not call macro FreeXid here since in a void func |
| @@ -1063,44 +1109,6 @@ out_reval: | |||
| 1063 | return rc; | 1109 | return rc; |
| 1064 | } | 1110 | } |
| 1065 | 1111 | ||
| 1066 | void posix_fill_in_inode(struct inode *tmp_inode, | ||
| 1067 | FILE_UNIX_BASIC_INFO *pData, int isNewInode) | ||
| 1068 | { | ||
| 1069 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
| 1070 | loff_t local_size; | ||
| 1071 | struct timespec local_mtime; | ||
| 1072 | |||
| 1073 | cifsInfo->time = jiffies; | ||
| 1074 | atomic_inc(&cifsInfo->inUse); | ||
| 1075 | |||
| 1076 | /* save mtime and size */ | ||
| 1077 | local_mtime = tmp_inode->i_mtime; | ||
| 1078 | local_size = tmp_inode->i_size; | ||
| 1079 | |||
| 1080 | cifs_unix_info_to_inode(tmp_inode, pData, 1); | ||
| 1081 | cifs_set_ops(tmp_inode, false); | ||
| 1082 | |||
| 1083 | if (!S_ISREG(tmp_inode->i_mode)) | ||
| 1084 | return; | ||
| 1085 | |||
| 1086 | /* | ||
| 1087 | * No sense invalidating pages for new inode | ||
| 1088 | * since we we have not started caching | ||
| 1089 | * readahead file data yet. | ||
| 1090 | */ | ||
| 1091 | if (isNewInode) | ||
| 1092 | return; | ||
| 1093 | |||
| 1094 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
| 1095 | (local_size == tmp_inode->i_size)) { | ||
| 1096 | cFYI(1, ("inode exists but unchanged")); | ||
| 1097 | } else { | ||
| 1098 | /* file may have changed on server */ | ||
| 1099 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
| 1100 | invalidate_remote_inode(tmp_inode); | ||
| 1101 | } | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | 1112 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) |
| 1105 | { | 1113 | { |
| 1106 | int rc = 0, tmprc; | 1114 | int rc = 0, tmprc; |
| @@ -1109,6 +1117,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1109 | struct cifsTconInfo *pTcon; | 1117 | struct cifsTconInfo *pTcon; |
| 1110 | char *full_path = NULL; | 1118 | char *full_path = NULL; |
| 1111 | struct inode *newinode = NULL; | 1119 | struct inode *newinode = NULL; |
| 1120 | struct cifs_fattr fattr; | ||
| 1112 | 1121 | ||
| 1113 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); | 1122 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); |
| 1114 | 1123 | ||
| @@ -1148,7 +1157,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1148 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 1157 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
| 1149 | d_drop(direntry); | 1158 | d_drop(direntry); |
| 1150 | } else { | 1159 | } else { |
| 1151 | __u64 unique_id; | ||
| 1152 | if (pInfo->Type == cpu_to_le32(-1)) { | 1160 | if (pInfo->Type == cpu_to_le32(-1)) { |
| 1153 | /* no return info, go query for it */ | 1161 | /* no return info, go query for it */ |
| 1154 | kfree(pInfo); | 1162 | kfree(pInfo); |
| @@ -1162,20 +1170,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1162 | else | 1170 | else |
| 1163 | direntry->d_op = &cifs_dentry_ops; | 1171 | direntry->d_op = &cifs_dentry_ops; |
| 1164 | 1172 | ||
| 1165 | unique_id = le64_to_cpu(pInfo->UniqueId); | 1173 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
| 1166 | newinode = cifs_new_inode(inode->i_sb, &unique_id); | 1174 | newinode = cifs_iget(inode->i_sb, &fattr); |
| 1167 | if (newinode == NULL) { | 1175 | if (!newinode) { |
| 1168 | kfree(pInfo); | 1176 | kfree(pInfo); |
| 1169 | goto mkdir_get_info; | 1177 | goto mkdir_get_info; |
| 1170 | } | 1178 | } |
| 1171 | 1179 | ||
| 1172 | newinode->i_nlink = 2; | ||
| 1173 | d_instantiate(direntry, newinode); | 1180 | d_instantiate(direntry, newinode); |
| 1174 | 1181 | ||
| 1175 | /* we already checked in POSIXCreate whether | ||
| 1176 | frame was long enough */ | ||
| 1177 | posix_fill_in_inode(direntry->d_inode, | ||
| 1178 | pInfo, 1 /* NewInode */); | ||
| 1179 | #ifdef CONFIG_CIFS_DEBUG2 | 1182 | #ifdef CONFIG_CIFS_DEBUG2 |
| 1180 | cFYI(1, ("instantiated dentry %p %s to inode %p", | 1183 | cFYI(1, ("instantiated dentry %p %s to inode %p", |
| 1181 | direntry, direntry->d_name.name, newinode)); | 1184 | direntry, direntry->d_name.name, newinode)); |
| @@ -1622,6 +1625,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 1622 | if (!err) { | 1625 | if (!err) { |
| 1623 | generic_fillattr(dentry->d_inode, stat); | 1626 | generic_fillattr(dentry->d_inode, stat); |
| 1624 | stat->blksize = CIFS_MAX_MSGSIZE; | 1627 | stat->blksize = CIFS_MAX_MSGSIZE; |
| 1628 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
| 1625 | } | 1629 | } |
| 1626 | return err; | 1630 | return err; |
| 1627 | } | 1631 | } |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 86d0055dc529..231aa6953f83 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -63,6 +63,55 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) | |||
| 63 | } | 63 | } |
| 64 | #endif /* DEBUG2 */ | 64 | #endif /* DEBUG2 */ |
| 65 | 65 | ||
| 66 | /* | ||
| 67 | * Find the dentry that matches "name". If there isn't one, create one. If it's | ||
| 68 | * a negative dentry or the uniqueid changed, then drop it and recreate it. | ||
| 69 | */ | ||
| 70 | static struct dentry * | ||
| 71 | cifs_readdir_lookup(struct dentry *parent, struct qstr *name, | ||
| 72 | struct cifs_fattr *fattr) | ||
| 73 | { | ||
| 74 | struct dentry *dentry, *alias; | ||
| 75 | struct inode *inode; | ||
| 76 | struct super_block *sb = parent->d_inode->i_sb; | ||
| 77 | |||
| 78 | cFYI(1, ("For %s", name->name)); | ||
| 79 | |||
| 80 | dentry = d_lookup(parent, name); | ||
| 81 | if (dentry) { | ||
| 82 | /* FIXME: check for inode number changes? */ | ||
| 83 | if (dentry->d_inode != NULL) | ||
| 84 | return dentry; | ||
| 85 | d_drop(dentry); | ||
| 86 | dput(dentry); | ||
| 87 | } | ||
| 88 | |||
| 89 | dentry = d_alloc(parent, name); | ||
| 90 | if (dentry == NULL) | ||
| 91 | return NULL; | ||
| 92 | |||
| 93 | inode = cifs_iget(sb, fattr); | ||
| 94 | if (!inode) { | ||
| 95 | dput(dentry); | ||
| 96 | return NULL; | ||
| 97 | } | ||
| 98 | |||
| 99 | if (CIFS_SB(sb)->tcon->nocase) | ||
| 100 | dentry->d_op = &cifs_ci_dentry_ops; | ||
| 101 | else | ||
| 102 | dentry->d_op = &cifs_dentry_ops; | ||
| 103 | |||
| 104 | alias = d_materialise_unique(dentry, inode); | ||
| 105 | if (alias != NULL) { | ||
| 106 | dput(dentry); | ||
| 107 | if (IS_ERR(alias)) | ||
| 108 | return NULL; | ||
| 109 | dentry = alias; | ||
| 110 | } | ||
| 111 | |||
| 112 | return dentry; | ||
| 113 | } | ||
| 114 | |||
| 66 | /* Returns 1 if new inode created, 2 if both dentry and inode were */ | 115 | /* Returns 1 if new inode created, 2 if both dentry and inode were */ |
| 67 | /* Might check in the future if inode number changed so we can rehash inode */ | 116 | /* Might check in the future if inode number changed so we can rehash inode */ |
| 68 | static int | 117 | static int |
| @@ -76,7 +125,6 @@ construct_dentry(struct qstr *qstring, struct file *file, | |||
| 76 | 125 | ||
| 77 | cFYI(1, ("For %s", qstring->name)); | 126 | cFYI(1, ("For %s", qstring->name)); |
| 78 | 127 | ||
| 79 | qstring->hash = full_name_hash(qstring->name, qstring->len); | ||
| 80 | tmp_dentry = d_lookup(file->f_path.dentry, qstring); | 128 | tmp_dentry = d_lookup(file->f_path.dentry, qstring); |
| 81 | if (tmp_dentry) { | 129 | if (tmp_dentry) { |
| 82 | /* BB: overwrite old name? i.e. tmp_dentry->d_name and | 130 | /* BB: overwrite old name? i.e. tmp_dentry->d_name and |
| @@ -299,140 +347,6 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
| 299 | } | 347 | } |
| 300 | } | 348 | } |
| 301 | 349 | ||
| 302 | static void unix_fill_in_inode(struct inode *tmp_inode, | ||
| 303 | FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode) | ||
| 304 | { | ||
| 305 | loff_t local_size; | ||
| 306 | struct timespec local_mtime; | ||
| 307 | |||
| 308 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
| 309 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
| 310 | |||
| 311 | __u32 type = le32_to_cpu(pfindData->Type); | ||
| 312 | __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes); | ||
| 313 | __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); | ||
| 314 | cifsInfo->time = jiffies; | ||
| 315 | atomic_inc(&cifsInfo->inUse); | ||
| 316 | |||
| 317 | /* save mtime and size */ | ||
| 318 | local_mtime = tmp_inode->i_mtime; | ||
| 319 | local_size = tmp_inode->i_size; | ||
| 320 | |||
| 321 | tmp_inode->i_atime = | ||
| 322 | cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
| 323 | tmp_inode->i_mtime = | ||
| 324 | cifs_NTtimeToUnix(pfindData->LastModificationTime); | ||
| 325 | tmp_inode->i_ctime = | ||
| 326 | cifs_NTtimeToUnix(pfindData->LastStatusChange); | ||
| 327 | |||
| 328 | tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); | ||
| 329 | /* since we set the inode type below we need to mask off type | ||
| 330 | to avoid strange results if bits above were corrupt */ | ||
| 331 | tmp_inode->i_mode &= ~S_IFMT; | ||
| 332 | if (type == UNIX_FILE) { | ||
| 333 | *pobject_type = DT_REG; | ||
| 334 | tmp_inode->i_mode |= S_IFREG; | ||
| 335 | } else if (type == UNIX_SYMLINK) { | ||
| 336 | *pobject_type = DT_LNK; | ||
| 337 | tmp_inode->i_mode |= S_IFLNK; | ||
| 338 | } else if (type == UNIX_DIR) { | ||
| 339 | *pobject_type = DT_DIR; | ||
| 340 | tmp_inode->i_mode |= S_IFDIR; | ||
| 341 | } else if (type == UNIX_CHARDEV) { | ||
| 342 | *pobject_type = DT_CHR; | ||
| 343 | tmp_inode->i_mode |= S_IFCHR; | ||
| 344 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), | ||
| 345 | le64_to_cpu(pfindData->DevMinor) & MINORMASK); | ||
| 346 | } else if (type == UNIX_BLOCKDEV) { | ||
| 347 | *pobject_type = DT_BLK; | ||
| 348 | tmp_inode->i_mode |= S_IFBLK; | ||
| 349 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), | ||
| 350 | le64_to_cpu(pfindData->DevMinor) & MINORMASK); | ||
| 351 | } else if (type == UNIX_FIFO) { | ||
| 352 | *pobject_type = DT_FIFO; | ||
| 353 | tmp_inode->i_mode |= S_IFIFO; | ||
| 354 | } else if (type == UNIX_SOCKET) { | ||
| 355 | *pobject_type = DT_SOCK; | ||
| 356 | tmp_inode->i_mode |= S_IFSOCK; | ||
| 357 | } else { | ||
| 358 | /* safest to just call it a file */ | ||
| 359 | *pobject_type = DT_REG; | ||
| 360 | tmp_inode->i_mode |= S_IFREG; | ||
| 361 | cFYI(1, ("unknown inode type %d", type)); | ||
| 362 | } | ||
| 363 | |||
| 364 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | ||
| 365 | tmp_inode->i_uid = cifs_sb->mnt_uid; | ||
| 366 | else | ||
| 367 | tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); | ||
| 368 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | ||
| 369 | tmp_inode->i_gid = cifs_sb->mnt_gid; | ||
| 370 | else | ||
| 371 | tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); | ||
| 372 | tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); | ||
| 373 | |||
| 374 | cifsInfo->server_eof = end_of_file; | ||
| 375 | spin_lock(&tmp_inode->i_lock); | ||
| 376 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
| 377 | /* can not safely change the file size here if the | ||
| 378 | client is writing to it due to potential races */ | ||
| 379 | i_size_write(tmp_inode, end_of_file); | ||
| 380 | |||
| 381 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
| 382 | /* for this calculation, not the real blocksize */ | ||
| 383 | tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
| 384 | } | ||
| 385 | spin_unlock(&tmp_inode->i_lock); | ||
| 386 | |||
| 387 | if (S_ISREG(tmp_inode->i_mode)) { | ||
| 388 | cFYI(1, ("File inode")); | ||
| 389 | tmp_inode->i_op = &cifs_file_inode_ops; | ||
| 390 | |||
| 391 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
| 392 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
| 393 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
| 394 | else | ||
| 395 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
| 396 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
| 397 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | ||
| 398 | else | ||
| 399 | tmp_inode->i_fop = &cifs_file_ops; | ||
| 400 | |||
| 401 | if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | ||
| 402 | (cifs_sb->tcon->ses->server->maxBuf < | ||
| 403 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | ||
| 404 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
| 405 | else | ||
| 406 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | ||
| 407 | |||
| 408 | if (isNewInode) | ||
| 409 | return; /* No sense invalidating pages for new inode | ||
| 410 | since we have not started caching readahead | ||
| 411 | file data for it yet */ | ||
| 412 | |||
| 413 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
| 414 | (local_size == tmp_inode->i_size)) { | ||
| 415 | cFYI(1, ("inode exists but unchanged")); | ||
| 416 | } else { | ||
| 417 | /* file may have changed on server */ | ||
| 418 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
| 419 | invalidate_remote_inode(tmp_inode); | ||
| 420 | } | ||
| 421 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
| 422 | cFYI(1, ("Directory inode")); | ||
| 423 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
| 424 | tmp_inode->i_fop = &cifs_dir_ops; | ||
| 425 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
| 426 | cFYI(1, ("Symbolic Link inode")); | ||
| 427 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
| 428 | /* tmp_inode->i_fop = *//* do not need to set to anything */ | ||
| 429 | } else { | ||
| 430 | cFYI(1, ("Special inode")); | ||
| 431 | init_special_inode(tmp_inode, tmp_inode->i_mode, | ||
| 432 | tmp_inode->i_rdev); | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | /* BB eventually need to add the following helper function to | 350 | /* BB eventually need to add the following helper function to |
| 437 | resolve NT_STATUS_STOPPED_ON_SYMLINK return code when | 351 | resolve NT_STATUS_STOPPED_ON_SYMLINK return code when |
| 438 | we try to do FindFirst on (NTFS) directory symlinks */ | 352 | we try to do FindFirst on (NTFS) directory symlinks */ |
| @@ -872,7 +786,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
| 872 | len = strnlen(filename, PATH_MAX); | 786 | len = strnlen(filename, PATH_MAX); |
| 873 | } | 787 | } |
| 874 | 788 | ||
| 875 | *pinum = le64_to_cpu(pFindData->UniqueId); | 789 | *pinum = le64_to_cpu(pFindData->basic.UniqueId); |
| 876 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { | 790 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { |
| 877 | FILE_DIRECTORY_INFO *pFindData = | 791 | FILE_DIRECTORY_INFO *pFindData = |
| 878 | (FILE_DIRECTORY_INFO *)current_entry; | 792 | (FILE_DIRECTORY_INFO *)current_entry; |
| @@ -934,9 +848,11 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
| 934 | struct cifsFileInfo *pCifsF; | 848 | struct cifsFileInfo *pCifsF; |
| 935 | unsigned int obj_type; | 849 | unsigned int obj_type; |
| 936 | __u64 inum; | 850 | __u64 inum; |
| 851 | ino_t ino; | ||
| 937 | struct cifs_sb_info *cifs_sb; | 852 | struct cifs_sb_info *cifs_sb; |
| 938 | struct inode *tmp_inode; | 853 | struct inode *tmp_inode; |
| 939 | struct dentry *tmp_dentry; | 854 | struct dentry *tmp_dentry; |
| 855 | struct cifs_fattr fattr; | ||
| 940 | 856 | ||
| 941 | /* get filename and len into qstring */ | 857 | /* get filename and len into qstring */ |
| 942 | /* get dentry */ | 858 | /* get dentry */ |
| @@ -967,39 +883,49 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
| 967 | return rc; | 883 | return rc; |
| 968 | 884 | ||
| 969 | /* only these two infolevels return valid inode numbers */ | 885 | /* only these two infolevels return valid inode numbers */ |
| 970 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX || | 886 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { |
| 971 | pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) | 887 | cifs_unix_basic_to_fattr(&fattr, |
| 972 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | 888 | &((FILE_UNIX_INFO *) pfindEntry)->basic, |
| 973 | &inum); | 889 | cifs_sb); |
| 974 | else | 890 | tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, |
| 975 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | 891 | &fattr); |
| 976 | NULL); | 892 | obj_type = fattr.cf_dtype; |
| 893 | ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); | ||
| 894 | } else { | ||
| 895 | if (pCifsF->srch_inf.info_level == | ||
| 896 | SMB_FIND_FILE_ID_FULL_DIR_INFO) | ||
| 897 | rc = construct_dentry(&qstring, file, &tmp_inode, | ||
| 898 | &tmp_dentry, &inum); | ||
| 899 | else | ||
| 900 | rc = construct_dentry(&qstring, file, &tmp_inode, | ||
| 901 | &tmp_dentry, NULL); | ||
| 977 | 902 | ||
| 978 | if ((tmp_inode == NULL) || (tmp_dentry == NULL)) | 903 | if ((tmp_inode == NULL) || (tmp_dentry == NULL)) { |
| 979 | return -ENOMEM; | 904 | rc = -ENOMEM; |
| 905 | goto out; | ||
| 906 | } | ||
| 980 | 907 | ||
| 981 | /* we pass in rc below, indicating whether it is a new inode, | 908 | /* we pass in rc below, indicating whether it is a new inode, |
| 982 | so we can figure out whether to invalidate the inode cached | 909 | * so we can figure out whether to invalidate the inode cached |
| 983 | data if the file has changed */ | 910 | * data if the file has changed |
| 984 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) | 911 | */ |
| 985 | unix_fill_in_inode(tmp_inode, | 912 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) |
| 986 | (FILE_UNIX_INFO *)pfindEntry, | 913 | fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc); |
| 987 | &obj_type, rc); | 914 | else |
| 988 | else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) | 915 | fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc); |
| 989 | fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */, | ||
| 990 | pfindEntry, &obj_type, rc); | ||
| 991 | else | ||
| 992 | fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); | ||
| 993 | 916 | ||
| 994 | if (rc) /* new inode - needs to be tied to dentry */ { | 917 | /* new inode - needs to be tied to dentry */ |
| 995 | d_instantiate(tmp_dentry, tmp_inode); | 918 | if (rc) { |
| 996 | if (rc == 2) | 919 | d_instantiate(tmp_dentry, tmp_inode); |
| 997 | d_rehash(tmp_dentry); | 920 | if (rc == 2) |
| 998 | } | 921 | d_rehash(tmp_dentry); |
| 922 | } | ||
| 999 | 923 | ||
| 924 | ino = cifs_uniqueid_to_ino_t(tmp_inode->i_ino); | ||
| 925 | } | ||
| 1000 | 926 | ||
| 1001 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, | 927 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, |
| 1002 | tmp_inode->i_ino, obj_type); | 928 | ino, obj_type); |
| 1003 | if (rc) { | 929 | if (rc) { |
| 1004 | cFYI(1, ("filldir rc = %d", rc)); | 930 | cFYI(1, ("filldir rc = %d", rc)); |
| 1005 | /* we can not return filldir errors to the caller | 931 | /* we can not return filldir errors to the caller |
| @@ -1008,6 +934,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
| 1008 | rc = -EOVERFLOW; | 934 | rc = -EOVERFLOW; |
| 1009 | } | 935 | } |
| 1010 | 936 | ||
| 937 | out: | ||
| 1011 | dput(tmp_dentry); | 938 | dput(tmp_dentry); |
| 1012 | return rc; | 939 | return rc; |
| 1013 | } | 940 | } |
