diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 762 |
1 files changed, 340 insertions, 422 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 155c9e785d0c..18afe57b2461 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -77,239 +77,202 @@ 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 | { |
84 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | ||
83 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 85 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
84 | struct cifsInodeInfo *cifsInfo = CIFS_I(inode); | 86 | unsigned long oldtime = cifs_i->time; |
85 | __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); | 87 | |
86 | __u64 end_of_file = le64_to_cpu(info->EndOfFile); | 88 | inode->i_atime = fattr->cf_atime; |
89 | inode->i_mtime = fattr->cf_mtime; | ||
90 | inode->i_ctime = fattr->cf_ctime; | ||
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 | /* if dynperm is set, don't clobber existing mode */ | ||
97 | if (inode->i_state & I_NEW || | ||
98 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) | ||
99 | inode->i_mode = fattr->cf_mode; | ||
100 | |||
101 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; | ||
102 | cifs_i->uniqueid = fattr->cf_uniqueid; | ||
103 | |||
104 | if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) | ||
105 | cifs_i->time = 0; | ||
106 | else | ||
107 | cifs_i->time = jiffies; | ||
108 | |||
109 | cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, | ||
110 | oldtime, cifs_i->time)); | ||
87 | 111 | ||
88 | inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime); | 112 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; |
89 | inode->i_mtime = | 113 | |
90 | cifs_NTtimeToUnix(info->LastModificationTime); | 114 | /* |
91 | inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange); | 115 | * Can't safely change the file size here if the client is writing to |
92 | inode->i_mode = le64_to_cpu(info->Permissions); | 116 | * it due to potential races. |
117 | */ | ||
118 | spin_lock(&inode->i_lock); | ||
119 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { | ||
120 | i_size_write(inode, fattr->cf_eof); | ||
121 | |||
122 | /* | ||
123 | * i_blocks is not related to (i_size / i_blksize), | ||
124 | * but instead 512 byte (2**9) size is required for | ||
125 | * calculating num blocks. | ||
126 | */ | ||
127 | inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; | ||
128 | } | ||
129 | spin_unlock(&inode->i_lock); | ||
130 | |||
131 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); | ||
132 | } | ||
133 | |||
134 | /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ | ||
135 | void | ||
136 | cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, | ||
137 | struct cifs_sb_info *cifs_sb) | ||
138 | { | ||
139 | memset(fattr, 0, sizeof(*fattr)); | ||
140 | fattr->cf_uniqueid = le64_to_cpu(info->UniqueId); | ||
141 | fattr->cf_bytes = le64_to_cpu(info->NumOfBytes); | ||
142 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | ||
143 | |||
144 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); | ||
145 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); | ||
146 | fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); | ||
147 | fattr->cf_mode = le64_to_cpu(info->Permissions); | ||
93 | 148 | ||
94 | /* | 149 | /* |
95 | * Since we set the inode type below we need to mask off | 150 | * Since we set the inode type below we need to mask off |
96 | * to avoid strange results if bits set above. | 151 | * to avoid strange results if bits set above. |
97 | */ | 152 | */ |
98 | inode->i_mode &= ~S_IFMT; | 153 | fattr->cf_mode &= ~S_IFMT; |
99 | switch (le32_to_cpu(info->Type)) { | 154 | switch (le32_to_cpu(info->Type)) { |
100 | case UNIX_FILE: | 155 | case UNIX_FILE: |
101 | inode->i_mode |= S_IFREG; | 156 | fattr->cf_mode |= S_IFREG; |
157 | fattr->cf_dtype = DT_REG; | ||
102 | break; | 158 | break; |
103 | case UNIX_SYMLINK: | 159 | case UNIX_SYMLINK: |
104 | inode->i_mode |= S_IFLNK; | 160 | fattr->cf_mode |= S_IFLNK; |
161 | fattr->cf_dtype = DT_LNK; | ||
105 | break; | 162 | break; |
106 | case UNIX_DIR: | 163 | case UNIX_DIR: |
107 | inode->i_mode |= S_IFDIR; | 164 | fattr->cf_mode |= S_IFDIR; |
165 | fattr->cf_dtype = DT_DIR; | ||
108 | break; | 166 | break; |
109 | case UNIX_CHARDEV: | 167 | case UNIX_CHARDEV: |
110 | inode->i_mode |= S_IFCHR; | 168 | fattr->cf_mode |= S_IFCHR; |
111 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 169 | fattr->cf_dtype = DT_CHR; |
112 | le64_to_cpu(info->DevMinor) & MINORMASK); | 170 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
171 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
113 | break; | 172 | break; |
114 | case UNIX_BLOCKDEV: | 173 | case UNIX_BLOCKDEV: |
115 | inode->i_mode |= S_IFBLK; | 174 | fattr->cf_mode |= S_IFBLK; |
116 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 175 | fattr->cf_dtype = DT_BLK; |
117 | le64_to_cpu(info->DevMinor) & MINORMASK); | 176 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
177 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
118 | break; | 178 | break; |
119 | case UNIX_FIFO: | 179 | case UNIX_FIFO: |
120 | inode->i_mode |= S_IFIFO; | 180 | fattr->cf_mode |= S_IFIFO; |
181 | fattr->cf_dtype = DT_FIFO; | ||
121 | break; | 182 | break; |
122 | case UNIX_SOCKET: | 183 | case UNIX_SOCKET: |
123 | inode->i_mode |= S_IFSOCK; | 184 | fattr->cf_mode |= S_IFSOCK; |
185 | fattr->cf_dtype = DT_SOCK; | ||
124 | break; | 186 | break; |
125 | default: | 187 | default: |
126 | /* safest to call it a file if we do not know */ | 188 | /* safest to call it a file if we do not know */ |
127 | inode->i_mode |= S_IFREG; | 189 | fattr->cf_mode |= S_IFREG; |
190 | fattr->cf_dtype = DT_REG; | ||
128 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); | 191 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); |
129 | break; | 192 | break; |
130 | } | 193 | } |
131 | 194 | ||
132 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && | 195 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
133 | !force_uid_gid) | 196 | fattr->cf_uid = cifs_sb->mnt_uid; |
134 | inode->i_uid = cifs_sb->mnt_uid; | ||
135 | else | 197 | else |
136 | inode->i_uid = le64_to_cpu(info->Uid); | 198 | fattr->cf_uid = le64_to_cpu(info->Uid); |
137 | 199 | ||
138 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && | 200 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
139 | !force_uid_gid) | 201 | fattr->cf_gid = cifs_sb->mnt_gid; |
140 | inode->i_gid = cifs_sb->mnt_gid; | ||
141 | else | 202 | else |
142 | inode->i_gid = le64_to_cpu(info->Gid); | 203 | fattr->cf_gid = le64_to_cpu(info->Gid); |
143 | |||
144 | inode->i_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 | 204 | ||
155 | /* | 205 | fattr->cf_nlink = le64_to_cpu(info->Nlinks); |
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 | } | 206 | } |
164 | 207 | ||
165 | |||
166 | /* | 208 | /* |
167 | * Needed to setup inode data for the directory which is the | 209 | * Fill a cifs_fattr struct with fake inode info. |
168 | * junction to the new submount (ie to setup the fake directory | ||
169 | * which represents a DFS referral) | ||
170 | */ | ||
171 | static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, | ||
172 | struct super_block *sb) | ||
173 | { | ||
174 | struct inode *pinode = NULL; | ||
175 | |||
176 | memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); | ||
177 | |||
178 | /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | ||
179 | __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); | ||
180 | __u64 UniqueId = 0; */ | ||
181 | pfnd_dat->LastStatusChange = | ||
182 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
183 | pfnd_dat->LastAccessTime = | ||
184 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
185 | pfnd_dat->LastModificationTime = | ||
186 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
187 | pfnd_dat->Type = cpu_to_le32(UNIX_DIR); | ||
188 | pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); | ||
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 | } | ||
202 | |||
203 | /** | ||
204 | * cifs_new inode - create new inode, initialize, and hash it | ||
205 | * @sb - pointer to superblock | ||
206 | * @inum - if valid pointer and serverino is enabled, replace i_ino with val | ||
207 | * | ||
208 | * Create a new inode, initialize it for CIFS and hash it. Returns the new | ||
209 | * inode or NULL if one couldn't be allocated. | ||
210 | * | 210 | * |
211 | * If the share isn't mounted with "serverino" or inum is a NULL pointer then | 211 | * Needed to setup cifs_fattr data for the directory which is the |
212 | * we'll just use the inode number assigned by new_inode(). Note that this can | 212 | * junction to the new submount (ie to setup the fake directory |
213 | * mean i_ino collisions since the i_ino assigned by new_inode is not | 213 | * which represents a DFS referral). |
214 | * guaranteed to be unique. | ||
215 | */ | 214 | */ |
216 | struct inode * | 215 | void |
217 | cifs_new_inode(struct super_block *sb, __u64 *inum) | 216 | cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) |
218 | { | 217 | { |
219 | struct inode *inode; | 218 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
220 | |||
221 | inode = new_inode(sb); | ||
222 | if (inode == NULL) | ||
223 | return NULL; | ||
224 | |||
225 | /* | ||
226 | * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we | ||
227 | * stop passing inum as ptr. Are there sanity checks we can use to | ||
228 | * ensure that the server is really filling in that field? Also, | ||
229 | * if serverino is disabled, perhaps we should be using iunique()? | ||
230 | */ | ||
231 | if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) | ||
232 | inode->i_ino = (unsigned long) *inum; | ||
233 | |||
234 | /* | ||
235 | * must set this here instead of cifs_alloc_inode since VFS will | ||
236 | * clobber i_flags | ||
237 | */ | ||
238 | if (sb->s_flags & MS_NOATIME) | ||
239 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
240 | |||
241 | insert_inode_hash(inode); | ||
242 | 219 | ||
243 | return inode; | 220 | cFYI(1, ("creating fake fattr for DFS referral")); |
221 | |||
222 | memset(fattr, 0, sizeof(*fattr)); | ||
223 | fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; | ||
224 | fattr->cf_uid = cifs_sb->mnt_uid; | ||
225 | fattr->cf_gid = cifs_sb->mnt_gid; | ||
226 | fattr->cf_atime = CURRENT_TIME; | ||
227 | fattr->cf_ctime = CURRENT_TIME; | ||
228 | fattr->cf_mtime = CURRENT_TIME; | ||
229 | fattr->cf_nlink = 2; | ||
230 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; | ||
244 | } | 231 | } |
245 | 232 | ||
246 | int cifs_get_inode_info_unix(struct inode **pinode, | 233 | int cifs_get_inode_info_unix(struct inode **pinode, |
247 | const unsigned char *full_path, struct super_block *sb, int xid) | 234 | const unsigned char *full_path, |
235 | struct super_block *sb, int xid) | ||
248 | { | 236 | { |
249 | int rc = 0; | 237 | int rc; |
250 | FILE_UNIX_BASIC_INFO find_data; | 238 | FILE_UNIX_BASIC_INFO find_data; |
251 | struct cifsTconInfo *pTcon; | 239 | struct cifs_fattr fattr; |
252 | struct inode *inode; | 240 | struct cifsTconInfo *tcon; |
253 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 241 | 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 | 242 | ||
259 | pTcon = cifs_sb->tcon; | 243 | tcon = cifs_sb->tcon; |
260 | cFYI(1, ("Getting info on %s", full_path)); | 244 | cFYI(1, ("Getting info on %s", full_path)); |
261 | 245 | ||
262 | /* could have done a find first instead but this returns more info */ | 246 | /* could have done a find first instead but this returns more info */ |
263 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, | 247 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
264 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 248 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
265 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 249 | 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 | 250 | ||
275 | num_of_bytes = le64_to_cpu(find_data.NumOfBytes); | 251 | if (!rc) { |
276 | end_of_file = le64_to_cpu(find_data.EndOfFile); | 252 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
253 | } else if (rc == -EREMOTE) { | ||
254 | cifs_create_dfs_fattr(&fattr, sb); | ||
255 | rc = 0; | ||
256 | } else { | ||
257 | return rc; | ||
258 | } | ||
277 | 259 | ||
278 | /* get new inode */ | ||
279 | if (*pinode == NULL) { | 260 | if (*pinode == NULL) { |
280 | __u64 unique_id = le64_to_cpu(find_data.UniqueId); | 261 | /* get new inode */ |
281 | *pinode = cifs_new_inode(sb, &unique_id); | 262 | *pinode = cifs_iget(sb, &fattr); |
282 | if (*pinode == NULL) { | 263 | if (!*pinode) |
283 | rc = -ENOMEM; | 264 | rc = -ENOMEM; |
284 | goto cgiiu_exit; | 265 | } else { |
285 | } | 266 | /* we already have inode, update it */ |
267 | cifs_fattr_to_inode(*pinode, &fattr); | ||
286 | } | 268 | } |
287 | 269 | ||
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; | 270 | return rc; |
308 | } | 271 | } |
309 | 272 | ||
310 | static int decode_sfu_inode(struct inode *inode, __u64 size, | 273 | static int |
311 | const unsigned char *path, | 274 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, |
312 | struct cifs_sb_info *cifs_sb, int xid) | 275 | struct cifs_sb_info *cifs_sb, int xid) |
313 | { | 276 | { |
314 | int rc; | 277 | int rc; |
315 | int oplock = 0; | 278 | int oplock = 0; |
@@ -321,10 +284,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
321 | 284 | ||
322 | pbuf = buf; | 285 | pbuf = buf; |
323 | 286 | ||
324 | if (size == 0) { | 287 | fattr->cf_mode &= ~S_IFMT; |
325 | inode->i_mode |= S_IFIFO; | 288 | |
289 | if (fattr->cf_eof == 0) { | ||
290 | fattr->cf_mode |= S_IFIFO; | ||
291 | fattr->cf_dtype = DT_FIFO; | ||
326 | return 0; | 292 | return 0; |
327 | } else if (size < 8) { | 293 | } else if (fattr->cf_eof < 8) { |
294 | fattr->cf_mode |= S_IFREG; | ||
295 | fattr->cf_dtype = DT_REG; | ||
328 | return -EINVAL; /* EOPNOTSUPP? */ | 296 | return -EINVAL; /* EOPNOTSUPP? */ |
329 | } | 297 | } |
330 | 298 | ||
@@ -336,42 +304,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
336 | if (rc == 0) { | 304 | if (rc == 0) { |
337 | int buf_type = CIFS_NO_BUFFER; | 305 | int buf_type = CIFS_NO_BUFFER; |
338 | /* Read header */ | 306 | /* Read header */ |
339 | rc = CIFSSMBRead(xid, pTcon, | 307 | rc = CIFSSMBRead(xid, pTcon, netfid, |
340 | netfid, | ||
341 | 24 /* length */, 0 /* offset */, | 308 | 24 /* length */, 0 /* offset */, |
342 | &bytes_read, &pbuf, &buf_type); | 309 | &bytes_read, &pbuf, &buf_type); |
343 | if ((rc == 0) && (bytes_read >= 8)) { | 310 | if ((rc == 0) && (bytes_read >= 8)) { |
344 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 311 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
345 | cFYI(1, ("Block device")); | 312 | cFYI(1, ("Block device")); |
346 | inode->i_mode |= S_IFBLK; | 313 | fattr->cf_mode |= S_IFBLK; |
314 | fattr->cf_dtype = DT_BLK; | ||
347 | if (bytes_read == 24) { | 315 | if (bytes_read == 24) { |
348 | /* we have enough to decode dev num */ | 316 | /* we have enough to decode dev num */ |
349 | __u64 mjr; /* major */ | 317 | __u64 mjr; /* major */ |
350 | __u64 mnr; /* minor */ | 318 | __u64 mnr; /* minor */ |
351 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 319 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
352 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 320 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
353 | inode->i_rdev = MKDEV(mjr, mnr); | 321 | fattr->cf_rdev = MKDEV(mjr, mnr); |
354 | } | 322 | } |
355 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | 323 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { |
356 | cFYI(1, ("Char device")); | 324 | cFYI(1, ("Char device")); |
357 | inode->i_mode |= S_IFCHR; | 325 | fattr->cf_mode |= S_IFCHR; |
326 | fattr->cf_dtype = DT_CHR; | ||
358 | if (bytes_read == 24) { | 327 | if (bytes_read == 24) { |
359 | /* we have enough to decode dev num */ | 328 | /* we have enough to decode dev num */ |
360 | __u64 mjr; /* major */ | 329 | __u64 mjr; /* major */ |
361 | __u64 mnr; /* minor */ | 330 | __u64 mnr; /* minor */ |
362 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 331 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
363 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 332 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
364 | inode->i_rdev = MKDEV(mjr, mnr); | 333 | fattr->cf_rdev = MKDEV(mjr, mnr); |
365 | } | 334 | } |
366 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | 335 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { |
367 | cFYI(1, ("Symlink")); | 336 | cFYI(1, ("Symlink")); |
368 | inode->i_mode |= S_IFLNK; | 337 | fattr->cf_mode |= S_IFLNK; |
338 | fattr->cf_dtype = DT_LNK; | ||
369 | } else { | 339 | } else { |
370 | inode->i_mode |= S_IFREG; /* file? */ | 340 | fattr->cf_mode |= S_IFREG; /* file? */ |
341 | fattr->cf_dtype = DT_REG; | ||
371 | rc = -EOPNOTSUPP; | 342 | rc = -EOPNOTSUPP; |
372 | } | 343 | } |
373 | } else { | 344 | } else { |
374 | inode->i_mode |= S_IFREG; /* then it is a file */ | 345 | fattr->cf_mode |= S_IFREG; /* then it is a file */ |
346 | fattr->cf_dtype = DT_REG; | ||
375 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 347 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ |
376 | } | 348 | } |
377 | CIFSSMBClose(xid, pTcon, netfid); | 349 | CIFSSMBClose(xid, pTcon, netfid); |
@@ -381,9 +353,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
381 | 353 | ||
382 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ | 354 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ |
383 | 355 | ||
384 | static int get_sfu_mode(struct inode *inode, | 356 | /* |
385 | const unsigned char *path, | 357 | * Fetch mode bits as provided by SFU. |
386 | struct cifs_sb_info *cifs_sb, int xid) | 358 | * |
359 | * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? | ||
360 | */ | ||
361 | static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | ||
362 | struct cifs_sb_info *cifs_sb, int xid) | ||
387 | { | 363 | { |
388 | #ifdef CONFIG_CIFS_XATTR | 364 | #ifdef CONFIG_CIFS_XATTR |
389 | ssize_t rc; | 365 | ssize_t rc; |
@@ -391,68 +367,80 @@ static int get_sfu_mode(struct inode *inode, | |||
391 | __u32 mode; | 367 | __u32 mode; |
392 | 368 | ||
393 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", | 369 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", |
394 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 370 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
395 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 371 | cifs_sb->mnt_cifs_flags & |
372 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
396 | if (rc < 0) | 373 | if (rc < 0) |
397 | return (int)rc; | 374 | return (int)rc; |
398 | else if (rc > 3) { | 375 | else if (rc > 3) { |
399 | mode = le32_to_cpu(*((__le32 *)ea_value)); | 376 | mode = le32_to_cpu(*((__le32 *)ea_value)); |
400 | inode->i_mode &= ~SFBITS_MASK; | 377 | fattr->cf_mode &= ~SFBITS_MASK; |
401 | cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode)); | 378 | cFYI(1, ("special bits 0%o org mode 0%o", mode, |
402 | inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; | 379 | fattr->cf_mode)); |
380 | fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; | ||
403 | cFYI(1, ("special mode bits 0%o", mode)); | 381 | cFYI(1, ("special mode bits 0%o", mode)); |
404 | return 0; | ||
405 | } else { | ||
406 | return 0; | ||
407 | } | 382 | } |
383 | |||
384 | return 0; | ||
408 | #else | 385 | #else |
409 | return -EOPNOTSUPP; | 386 | return -EOPNOTSUPP; |
410 | #endif | 387 | #endif |
411 | } | 388 | } |
412 | 389 | ||
413 | /* | 390 | /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ |
414 | * Needed to setup inode data for the directory which is the | 391 | void |
415 | * junction to the new submount (ie to setup the fake directory | 392 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, |
416 | * which represents a DFS referral) | 393 | struct cifs_sb_info *cifs_sb, bool adjust_tz) |
417 | */ | ||
418 | static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, | ||
419 | struct super_block *sb) | ||
420 | { | 394 | { |
421 | memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); | 395 | memset(fattr, 0, sizeof(*fattr)); |
422 | 396 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); | |
423 | /* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); | 397 | if (info->DeletePending) |
424 | __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | 398 | fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING; |
425 | __u8 pfnd_dat->DeletePending = 0; | 399 | |
426 | __u8 pfnd_data->Directory = 0; | 400 | if (info->LastAccessTime) |
427 | __le32 pfnd_dat->EASize = 0; | 401 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
428 | __u64 pfnd_dat->IndexNumber = 0; | 402 | else |
429 | __u64 pfnd_dat->IndexNumber1 = 0; */ | 403 | fattr->cf_atime = CURRENT_TIME; |
430 | pfnd_dat->CreationTime = | 404 | |
431 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 405 | fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); |
432 | pfnd_dat->LastAccessTime = | 406 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); |
433 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 407 | |
434 | pfnd_dat->LastWriteTime = | 408 | if (adjust_tz) { |
435 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 409 | fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; |
436 | pfnd_dat->ChangeTime = | 410 | fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; |
437 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 411 | } |
438 | pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); | 412 | |
439 | pfnd_dat->NumberOfLinks = cpu_to_le32(2); | 413 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
414 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); | ||
415 | |||
416 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | ||
417 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | ||
418 | fattr->cf_dtype = DT_DIR; | ||
419 | } else { | ||
420 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; | ||
421 | fattr->cf_dtype = DT_REG; | ||
422 | |||
423 | /* clear write bits if ATTR_READONLY is set */ | ||
424 | if (fattr->cf_cifsattrs & ATTR_READONLY) | ||
425 | fattr->cf_mode &= ~(S_IWUGO); | ||
426 | } | ||
427 | |||
428 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | ||
429 | |||
430 | fattr->cf_uid = cifs_sb->mnt_uid; | ||
431 | fattr->cf_gid = cifs_sb->mnt_gid; | ||
440 | } | 432 | } |
441 | 433 | ||
442 | int cifs_get_inode_info(struct inode **pinode, | 434 | int cifs_get_inode_info(struct inode **pinode, |
443 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, | 435 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, |
444 | struct super_block *sb, int xid, const __u16 *pfid) | 436 | struct super_block *sb, int xid, const __u16 *pfid) |
445 | { | 437 | { |
446 | int rc = 0; | 438 | int rc = 0, tmprc; |
447 | __u32 attr; | ||
448 | struct cifsInodeInfo *cifsInfo; | ||
449 | struct cifsTconInfo *pTcon; | 439 | struct cifsTconInfo *pTcon; |
450 | struct inode *inode; | ||
451 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 440 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
452 | char *buf = NULL; | 441 | char *buf = NULL; |
453 | bool adjustTZ = false; | 442 | bool adjustTZ = false; |
454 | bool is_dfs_referral = false; | 443 | struct cifs_fattr fattr; |
455 | umode_t default_mode; | ||
456 | 444 | ||
457 | pTcon = cifs_sb->tcon; | 445 | pTcon = cifs_sb->tcon; |
458 | cFYI(1, ("Getting info on %s", full_path)); | 446 | cFYI(1, ("Getting info on %s", full_path)); |
@@ -487,163 +475,82 @@ int cifs_get_inode_info(struct inode **pinode, | |||
487 | adjustTZ = true; | 475 | adjustTZ = true; |
488 | } | 476 | } |
489 | } | 477 | } |
490 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 478 | |
491 | if (rc == -EREMOTE) { | 479 | if (!rc) { |
492 | is_dfs_referral = true; | 480 | cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, |
493 | fill_fake_finddata(pfindData, sb); | 481 | cifs_sb, adjustTZ); |
482 | } else if (rc == -EREMOTE) { | ||
483 | cifs_create_dfs_fattr(&fattr, sb); | ||
494 | rc = 0; | 484 | rc = 0; |
495 | } else if (rc) | 485 | } else { |
496 | goto cgii_exit; | 486 | goto cgii_exit; |
487 | } | ||
497 | 488 | ||
498 | attr = le32_to_cpu(pfindData->Attributes); | 489 | /* |
499 | 490 | * If an inode wasn't passed in, then get the inode number | |
500 | /* get new inode */ | 491 | * |
492 | * Is an i_ino of zero legal? Can we use that to check if the server | ||
493 | * supports returning inode numbers? Are there other sanity checks we | ||
494 | * can use to ensure that the server is really filling in that field? | ||
495 | * | ||
496 | * We can not use the IndexNumber field by default from Windows or | ||
497 | * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA | ||
498 | * CIFS spec claims that this value is unique within the scope of a | ||
499 | * share, and the windows docs hint that it's actually unique | ||
500 | * per-machine. | ||
501 | * | ||
502 | * There may be higher info levels that work but are there Windows | ||
503 | * server or network appliances for which IndexNumber field is not | ||
504 | * guaranteed unique? | ||
505 | */ | ||
501 | if (*pinode == NULL) { | 506 | if (*pinode == NULL) { |
502 | __u64 inode_num; | ||
503 | __u64 *pinum = &inode_num; | ||
504 | |||
505 | /* Is an i_ino of zero legal? Can we use that to check | ||
506 | if the server supports returning inode numbers? Are | ||
507 | there other sanity checks we can use to ensure that | ||
508 | the server is really filling in that field? */ | ||
509 | |||
510 | /* We can not use the IndexNumber field by default from | ||
511 | Windows or Samba (in ALL_INFO buf) but we can request | ||
512 | it explicitly. It may not be unique presumably if | ||
513 | the server has multiple devices mounted under one share */ | ||
514 | |||
515 | /* There may be higher info levels that work but are | ||
516 | there Windows server or network appliances for which | ||
517 | IndexNumber field is not guaranteed unique? */ | ||
518 | |||
519 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 507 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
520 | int rc1 = 0; | 508 | int rc1 = 0; |
521 | 509 | ||
522 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | 510 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, |
523 | full_path, pinum, | 511 | full_path, &fattr.cf_uniqueid, |
524 | cifs_sb->local_nls, | 512 | cifs_sb->local_nls, |
525 | cifs_sb->mnt_cifs_flags & | 513 | cifs_sb->mnt_cifs_flags & |
526 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 514 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
527 | if (rc1) { | 515 | if (rc1) { |
528 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | ||
529 | pinum = NULL; | ||
530 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 516 | /* BB EOPNOSUPP disable SERVER_INUM? */ |
517 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | ||
518 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | ||
531 | } | 519 | } |
532 | } else { | 520 | } else { |
533 | pinum = NULL; | 521 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
534 | } | ||
535 | |||
536 | *pinode = cifs_new_inode(sb, pinum); | ||
537 | if (*pinode == NULL) { | ||
538 | rc = -ENOMEM; | ||
539 | goto cgii_exit; | ||
540 | } | 522 | } |
541 | } | ||
542 | inode = *pinode; | ||
543 | cifsInfo = CIFS_I(inode); | ||
544 | cifsInfo->cifsAttrs = attr; | ||
545 | cifsInfo->delete_pending = pfindData->DeletePending ? true : false; | ||
546 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
547 | cifsInfo->time = jiffies; | ||
548 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
549 | |||
550 | /* blksize needs to be multiple of two. So safer to default to | ||
551 | blksize and blkbits set in superblock so 2**blkbits and blksize | ||
552 | will match rather than setting to: | ||
553 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | ||
554 | |||
555 | /* Linux can not store file creation time so ignore it */ | ||
556 | if (pfindData->LastAccessTime) | ||
557 | inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
558 | else /* do not need to use current_fs_time - time not stored */ | ||
559 | inode->i_atime = CURRENT_TIME; | ||
560 | inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime); | ||
561 | inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime); | ||
562 | cFYI(DBG2, ("Attributes came in as 0x%x", attr)); | ||
563 | if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { | ||
564 | inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; | ||
565 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; | ||
566 | } | ||
567 | |||
568 | /* get default inode mode */ | ||
569 | if (attr & ATTR_DIRECTORY) | ||
570 | default_mode = cifs_sb->mnt_dir_mode; | ||
571 | else | ||
572 | default_mode = cifs_sb->mnt_file_mode; | ||
573 | |||
574 | /* set permission bits */ | ||
575 | if (atomic_read(&cifsInfo->inUse) == 0 || | ||
576 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
577 | inode->i_mode = default_mode; | ||
578 | else { | ||
579 | /* just reenable write bits if !ATTR_READONLY */ | ||
580 | if ((inode->i_mode & S_IWUGO) == 0 && | ||
581 | (attr & ATTR_READONLY) == 0) | ||
582 | inode->i_mode |= (S_IWUGO & default_mode); | ||
583 | |||
584 | inode->i_mode &= ~S_IFMT; | ||
585 | } | ||
586 | /* clear write bits if ATTR_READONLY is set */ | ||
587 | if (attr & ATTR_READONLY) | ||
588 | inode->i_mode &= ~S_IWUGO; | ||
589 | |||
590 | /* set inode type */ | ||
591 | if ((attr & ATTR_SYSTEM) && | ||
592 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { | ||
593 | /* no need to fix endianness on 0 */ | ||
594 | if (pfindData->EndOfFile == 0) | ||
595 | inode->i_mode |= S_IFIFO; | ||
596 | else if (decode_sfu_inode(inode, | ||
597 | le64_to_cpu(pfindData->EndOfFile), | ||
598 | full_path, cifs_sb, xid)) | ||
599 | cFYI(1, ("unknown SFU file type\n")); | ||
600 | } else { | 523 | } else { |
601 | if (attr & ATTR_DIRECTORY) | 524 | fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; |
602 | inode->i_mode |= S_IFDIR; | ||
603 | else | ||
604 | inode->i_mode |= S_IFREG; | ||
605 | } | 525 | } |
606 | 526 | ||
607 | cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); | 527 | /* query for SFU type info if supported and needed */ |
608 | spin_lock(&inode->i_lock); | 528 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
609 | if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { | 529 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
610 | /* can not safely shrink the file size here if the | 530 | tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); |
611 | client is writing to it due to potential races */ | 531 | if (tmprc) |
612 | i_size_write(inode, cifsInfo->server_eof); | 532 | cFYI(1, ("cifs_sfu_type failed: %d", tmprc)); |
613 | |||
614 | /* 512 bytes (2**9) is the fake blocksize that must be | ||
615 | used for this calculation */ | ||
616 | inode->i_blocks = (512 - 1 + le64_to_cpu( | ||
617 | pfindData->AllocationSize)) >> 9; | ||
618 | } | 533 | } |
619 | spin_unlock(&inode->i_lock); | ||
620 | 534 | ||
621 | inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); | ||
622 | |||
623 | /* BB fill in uid and gid here? with help from winbind? | ||
624 | or retrieve from NTFS stream extended attribute */ | ||
625 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 535 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
626 | /* fill in 0777 bits from ACL */ | 536 | /* fill in 0777 bits from ACL */ |
627 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 537 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
628 | cFYI(1, ("Getting mode bits from ACL")); | 538 | cFYI(1, ("Getting mode bits from ACL")); |
629 | acl_to_uid_mode(cifs_sb, inode, full_path, pfid); | 539 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); |
630 | } | 540 | } |
631 | #endif | 541 | #endif |
632 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | ||
633 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
634 | get_sfu_mode(inode, full_path, cifs_sb, xid); | ||
635 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | ||
636 | inode->i_uid = cifs_sb->mnt_uid; | ||
637 | inode->i_gid = cifs_sb->mnt_gid; | ||
638 | /* set so we do not keep refreshing these fields with | ||
639 | bad data after user has changed them in memory */ | ||
640 | atomic_set(&cifsInfo->inUse, 1); | ||
641 | } | ||
642 | |||
643 | cifs_set_ops(inode, is_dfs_referral); | ||
644 | |||
645 | 542 | ||
543 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
544 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | ||
545 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); | ||
646 | 546 | ||
547 | if (!*pinode) { | ||
548 | *pinode = cifs_iget(sb, &fattr); | ||
549 | if (!*pinode) | ||
550 | rc = -ENOMEM; | ||
551 | } else { | ||
552 | cifs_fattr_to_inode(*pinode, &fattr); | ||
553 | } | ||
647 | 554 | ||
648 | cgii_exit: | 555 | cgii_exit: |
649 | kfree(buf); | 556 | kfree(buf); |
@@ -695,33 +602,78 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
695 | return full_path; | 602 | return full_path; |
696 | } | 603 | } |
697 | 604 | ||
605 | static int | ||
606 | cifs_find_inode(struct inode *inode, void *opaque) | ||
607 | { | ||
608 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
609 | |||
610 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | ||
611 | return 0; | ||
612 | |||
613 | return 1; | ||
614 | } | ||
615 | |||
616 | static int | ||
617 | cifs_init_inode(struct inode *inode, void *opaque) | ||
618 | { | ||
619 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
620 | |||
621 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | /* Given fattrs, get a corresponding inode */ | ||
626 | struct inode * | ||
627 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | ||
628 | { | ||
629 | unsigned long hash; | ||
630 | struct inode *inode; | ||
631 | |||
632 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); | ||
633 | |||
634 | /* hash down to 32-bits on 32-bit arch */ | ||
635 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); | ||
636 | |||
637 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | ||
638 | |||
639 | /* we have fattrs in hand, update the inode */ | ||
640 | if (inode) { | ||
641 | cifs_fattr_to_inode(inode, fattr); | ||
642 | if (sb->s_flags & MS_NOATIME) | ||
643 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
644 | if (inode->i_state & I_NEW) { | ||
645 | inode->i_ino = hash; | ||
646 | unlock_new_inode(inode); | ||
647 | } | ||
648 | } | ||
649 | |||
650 | return inode; | ||
651 | } | ||
652 | |||
698 | /* gets root inode */ | 653 | /* gets root inode */ |
699 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 654 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) |
700 | { | 655 | { |
701 | int xid; | 656 | int xid; |
702 | struct cifs_sb_info *cifs_sb; | 657 | struct cifs_sb_info *cifs_sb; |
703 | struct inode *inode; | 658 | struct inode *inode = NULL; |
704 | long rc; | 659 | long rc; |
705 | char *full_path; | 660 | char *full_path; |
706 | 661 | ||
707 | inode = iget_locked(sb, ino); | 662 | 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); | 663 | full_path = cifs_build_path_to_root(cifs_sb); |
715 | if (full_path == NULL) | 664 | if (full_path == NULL) |
716 | return ERR_PTR(-ENOMEM); | 665 | return ERR_PTR(-ENOMEM); |
717 | 666 | ||
718 | xid = GetXid(); | 667 | xid = GetXid(); |
719 | if (cifs_sb->tcon->unix_ext) | 668 | if (cifs_sb->tcon->unix_ext) |
720 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, | 669 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
721 | xid); | ||
722 | else | 670 | else |
723 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, | 671 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
724 | xid, NULL); | 672 | xid, NULL); |
673 | |||
674 | if (!inode) | ||
675 | return ERR_PTR(-ENOMEM); | ||
676 | |||
725 | if (rc && cifs_sb->tcon->ipc) { | 677 | if (rc && cifs_sb->tcon->ipc) { |
726 | cFYI(1, ("ipc connection - fake read inode")); | 678 | cFYI(1, ("ipc connection - fake read inode")); |
727 | inode->i_mode |= S_IFDIR; | 679 | inode->i_mode |= S_IFDIR; |
@@ -737,7 +689,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
737 | return ERR_PTR(rc); | 689 | return ERR_PTR(rc); |
738 | } | 690 | } |
739 | 691 | ||
740 | unlock_new_inode(inode); | ||
741 | 692 | ||
742 | kfree(full_path); | 693 | kfree(full_path); |
743 | /* can not call macro FreeXid here since in a void func | 694 | /* can not call macro FreeXid here since in a void func |
@@ -1063,44 +1014,6 @@ out_reval: | |||
1063 | return rc; | 1014 | return rc; |
1064 | } | 1015 | } |
1065 | 1016 | ||
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) | 1017 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) |
1105 | { | 1018 | { |
1106 | int rc = 0, tmprc; | 1019 | int rc = 0, tmprc; |
@@ -1109,6 +1022,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1109 | struct cifsTconInfo *pTcon; | 1022 | struct cifsTconInfo *pTcon; |
1110 | char *full_path = NULL; | 1023 | char *full_path = NULL; |
1111 | struct inode *newinode = NULL; | 1024 | struct inode *newinode = NULL; |
1025 | struct cifs_fattr fattr; | ||
1112 | 1026 | ||
1113 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); | 1027 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); |
1114 | 1028 | ||
@@ -1148,7 +1062,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1148 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 1062 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
1149 | d_drop(direntry); | 1063 | d_drop(direntry); |
1150 | } else { | 1064 | } else { |
1151 | __u64 unique_id; | ||
1152 | if (pInfo->Type == cpu_to_le32(-1)) { | 1065 | if (pInfo->Type == cpu_to_le32(-1)) { |
1153 | /* no return info, go query for it */ | 1066 | /* no return info, go query for it */ |
1154 | kfree(pInfo); | 1067 | kfree(pInfo); |
@@ -1162,20 +1075,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1162 | else | 1075 | else |
1163 | direntry->d_op = &cifs_dentry_ops; | 1076 | direntry->d_op = &cifs_dentry_ops; |
1164 | 1077 | ||
1165 | unique_id = le64_to_cpu(pInfo->UniqueId); | 1078 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
1166 | newinode = cifs_new_inode(inode->i_sb, &unique_id); | 1079 | newinode = cifs_iget(inode->i_sb, &fattr); |
1167 | if (newinode == NULL) { | 1080 | if (!newinode) { |
1168 | kfree(pInfo); | 1081 | kfree(pInfo); |
1169 | goto mkdir_get_info; | 1082 | goto mkdir_get_info; |
1170 | } | 1083 | } |
1171 | 1084 | ||
1172 | newinode->i_nlink = 2; | ||
1173 | d_instantiate(direntry, newinode); | 1085 | d_instantiate(direntry, newinode); |
1174 | 1086 | ||
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 | 1087 | #ifdef CONFIG_CIFS_DEBUG2 |
1180 | cFYI(1, ("instantiated dentry %p %s to inode %p", | 1088 | cFYI(1, ("instantiated dentry %p %s to inode %p", |
1181 | direntry, direntry->d_name.name, newinode)); | 1089 | direntry, direntry->d_name.name, newinode)); |
@@ -1238,10 +1146,10 @@ mkdir_get_info: | |||
1238 | args.uid = NO_CHANGE_64; | 1146 | args.uid = NO_CHANGE_64; |
1239 | args.gid = NO_CHANGE_64; | 1147 | args.gid = NO_CHANGE_64; |
1240 | } | 1148 | } |
1241 | CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | 1149 | CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, |
1242 | cifs_sb->local_nls, | 1150 | cifs_sb->local_nls, |
1243 | cifs_sb->mnt_cifs_flags & | 1151 | cifs_sb->mnt_cifs_flags & |
1244 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1152 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1245 | } else { | 1153 | } else { |
1246 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | 1154 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && |
1247 | (mode & S_IWUGO) == 0) { | 1155 | (mode & S_IWUGO) == 0) { |
@@ -1622,6 +1530,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1622 | if (!err) { | 1530 | if (!err) { |
1623 | generic_fillattr(dentry->d_inode, stat); | 1531 | generic_fillattr(dentry->d_inode, stat); |
1624 | stat->blksize = CIFS_MAX_MSGSIZE; | 1532 | stat->blksize = CIFS_MAX_MSGSIZE; |
1533 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
1625 | } | 1534 | } |
1626 | return err; | 1535 | return err; |
1627 | } | 1536 | } |
@@ -1786,6 +1695,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1786 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1695 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1787 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1696 | struct cifsTconInfo *pTcon = cifs_sb->tcon; |
1788 | struct cifs_unix_set_info_args *args = NULL; | 1697 | struct cifs_unix_set_info_args *args = NULL; |
1698 | struct cifsFileInfo *open_file; | ||
1789 | 1699 | ||
1790 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", | 1700 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", |
1791 | direntry->d_name.name, attrs->ia_valid)); | 1701 | direntry->d_name.name, attrs->ia_valid)); |
@@ -1872,10 +1782,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1872 | args->ctime = NO_CHANGE_64; | 1782 | args->ctime = NO_CHANGE_64; |
1873 | 1783 | ||
1874 | args->device = 0; | 1784 | args->device = 0; |
1875 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, | 1785 | open_file = find_writable_file(cifsInode); |
1876 | cifs_sb->local_nls, | 1786 | if (open_file) { |
1877 | cifs_sb->mnt_cifs_flags & | 1787 | u16 nfid = open_file->netfid; |
1878 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1788 | u32 npid = open_file->pid; |
1789 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | ||
1790 | atomic_dec(&open_file->wrtPending); | ||
1791 | } else { | ||
1792 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | ||
1793 | cifs_sb->local_nls, | ||
1794 | cifs_sb->mnt_cifs_flags & | ||
1795 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1796 | } | ||
1879 | 1797 | ||
1880 | if (!rc) | 1798 | if (!rc) |
1881 | rc = inode_setattr(inode, attrs); | 1799 | rc = inode_setattr(inode, attrs); |