diff options
author | Dan Williams <dan.j.williams@intel.com> | 2009-09-08 20:55:54 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2009-09-08 20:55:54 -0400 |
commit | 9134d02bc0af4a8747d448d1f811ec5f8eb96df6 (patch) | |
tree | 704c3e5dcc10f360815c4868a74711f82fb62e27 /fs/cifs/inode.c | |
parent | bbb20089a3275a19e475dbc21320c3742e3ca423 (diff) | |
parent | 80ffb3cceaefa405f2ecd46d66500ed8d53efe74 (diff) |
Merge commit 'md/for-linus' into async-tx-next
Conflicts:
drivers/md/raid5.c
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 780 |
1 files changed, 353 insertions, 427 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fad882b075b..82d83839655 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 | static 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 | static 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,85 @@ 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)); | 516 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); |
529 | pinum = NULL; | 517 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
530 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 518 | /* disable serverino if call not supported */ |
519 | if (rc1 == -EINVAL) | ||
520 | cifs_sb->mnt_cifs_flags &= | ||
521 | ~CIFS_MOUNT_SERVER_INUM; | ||
531 | } | 522 | } |
532 | } else { | 523 | } else { |
533 | pinum = NULL; | 524 | 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 | } | 525 | } |
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 { | 526 | } else { |
601 | if (attr & ATTR_DIRECTORY) | 527 | fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; |
602 | inode->i_mode |= S_IFDIR; | ||
603 | else | ||
604 | inode->i_mode |= S_IFREG; | ||
605 | } | 528 | } |
606 | 529 | ||
607 | cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); | 530 | /* query for SFU type info if supported and needed */ |
608 | spin_lock(&inode->i_lock); | 531 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
609 | if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { | 532 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
610 | /* can not safely shrink the file size here if the | 533 | tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); |
611 | client is writing to it due to potential races */ | 534 | if (tmprc) |
612 | i_size_write(inode, cifsInfo->server_eof); | 535 | 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 | } | 536 | } |
619 | spin_unlock(&inode->i_lock); | ||
620 | 537 | ||
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 | 538 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
626 | /* fill in 0777 bits from ACL */ | 539 | /* fill in 0777 bits from ACL */ |
627 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 540 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
628 | cFYI(1, ("Getting mode bits from ACL")); | 541 | cFYI(1, ("Getting mode bits from ACL")); |
629 | acl_to_uid_mode(cifs_sb, inode, full_path, pfid); | 542 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); |
630 | } | 543 | } |
631 | #endif | 544 | #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 | 545 | ||
546 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
547 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | ||
548 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); | ||
646 | 549 | ||
550 | if (!*pinode) { | ||
551 | *pinode = cifs_iget(sb, &fattr); | ||
552 | if (!*pinode) | ||
553 | rc = -ENOMEM; | ||
554 | } else { | ||
555 | cifs_fattr_to_inode(*pinode, &fattr); | ||
556 | } | ||
647 | 557 | ||
648 | cgii_exit: | 558 | cgii_exit: |
649 | kfree(buf); | 559 | kfree(buf); |
@@ -695,33 +605,78 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
695 | return full_path; | 605 | return full_path; |
696 | } | 606 | } |
697 | 607 | ||
608 | static int | ||
609 | cifs_find_inode(struct inode *inode, void *opaque) | ||
610 | { | ||
611 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
612 | |||
613 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | ||
614 | return 0; | ||
615 | |||
616 | return 1; | ||
617 | } | ||
618 | |||
619 | static int | ||
620 | cifs_init_inode(struct inode *inode, void *opaque) | ||
621 | { | ||
622 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
623 | |||
624 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | /* Given fattrs, get a corresponding inode */ | ||
629 | struct inode * | ||
630 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | ||
631 | { | ||
632 | unsigned long hash; | ||
633 | struct inode *inode; | ||
634 | |||
635 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); | ||
636 | |||
637 | /* hash down to 32-bits on 32-bit arch */ | ||
638 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); | ||
639 | |||
640 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | ||
641 | |||
642 | /* we have fattrs in hand, update the inode */ | ||
643 | if (inode) { | ||
644 | cifs_fattr_to_inode(inode, fattr); | ||
645 | if (sb->s_flags & MS_NOATIME) | ||
646 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
647 | if (inode->i_state & I_NEW) { | ||
648 | inode->i_ino = hash; | ||
649 | unlock_new_inode(inode); | ||
650 | } | ||
651 | } | ||
652 | |||
653 | return inode; | ||
654 | } | ||
655 | |||
698 | /* gets root inode */ | 656 | /* gets root inode */ |
699 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 657 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) |
700 | { | 658 | { |
701 | int xid; | 659 | int xid; |
702 | struct cifs_sb_info *cifs_sb; | 660 | struct cifs_sb_info *cifs_sb; |
703 | struct inode *inode; | 661 | struct inode *inode = NULL; |
704 | long rc; | 662 | long rc; |
705 | char *full_path; | 663 | char *full_path; |
706 | 664 | ||
707 | inode = iget_locked(sb, ino); | 665 | 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); | 666 | full_path = cifs_build_path_to_root(cifs_sb); |
715 | if (full_path == NULL) | 667 | if (full_path == NULL) |
716 | return ERR_PTR(-ENOMEM); | 668 | return ERR_PTR(-ENOMEM); |
717 | 669 | ||
718 | xid = GetXid(); | 670 | xid = GetXid(); |
719 | if (cifs_sb->tcon->unix_ext) | 671 | if (cifs_sb->tcon->unix_ext) |
720 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, | 672 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
721 | xid); | ||
722 | else | 673 | else |
723 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, | 674 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
724 | xid, NULL); | 675 | xid, NULL); |
676 | |||
677 | if (!inode) | ||
678 | return ERR_PTR(-ENOMEM); | ||
679 | |||
725 | if (rc && cifs_sb->tcon->ipc) { | 680 | if (rc && cifs_sb->tcon->ipc) { |
726 | cFYI(1, ("ipc connection - fake read inode")); | 681 | cFYI(1, ("ipc connection - fake read inode")); |
727 | inode->i_mode |= S_IFDIR; | 682 | inode->i_mode |= S_IFDIR; |
@@ -737,7 +692,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
737 | return ERR_PTR(rc); | 692 | return ERR_PTR(rc); |
738 | } | 693 | } |
739 | 694 | ||
740 | unlock_new_inode(inode); | ||
741 | 695 | ||
742 | kfree(full_path); | 696 | kfree(full_path); |
743 | /* can not call macro FreeXid here since in a void func | 697 | /* can not call macro FreeXid here since in a void func |
@@ -988,8 +942,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
988 | * sb->s_vfs_rename_mutex here */ | 942 | * sb->s_vfs_rename_mutex here */ |
989 | full_path = build_path_from_dentry(dentry); | 943 | full_path = build_path_from_dentry(dentry); |
990 | if (full_path == NULL) { | 944 | if (full_path == NULL) { |
945 | rc = -ENOMEM; | ||
991 | FreeXid(xid); | 946 | FreeXid(xid); |
992 | return -ENOMEM; | 947 | return rc; |
993 | } | 948 | } |
994 | 949 | ||
995 | if ((tcon->ses->capabilities & CAP_UNIX) && | 950 | if ((tcon->ses->capabilities & CAP_UNIX) && |
@@ -1062,44 +1017,6 @@ out_reval: | |||
1062 | return rc; | 1017 | return rc; |
1063 | } | 1018 | } |
1064 | 1019 | ||
1065 | void posix_fill_in_inode(struct inode *tmp_inode, | ||
1066 | FILE_UNIX_BASIC_INFO *pData, int isNewInode) | ||
1067 | { | ||
1068 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
1069 | loff_t local_size; | ||
1070 | struct timespec local_mtime; | ||
1071 | |||
1072 | cifsInfo->time = jiffies; | ||
1073 | atomic_inc(&cifsInfo->inUse); | ||
1074 | |||
1075 | /* save mtime and size */ | ||
1076 | local_mtime = tmp_inode->i_mtime; | ||
1077 | local_size = tmp_inode->i_size; | ||
1078 | |||
1079 | cifs_unix_info_to_inode(tmp_inode, pData, 1); | ||
1080 | cifs_set_ops(tmp_inode, false); | ||
1081 | |||
1082 | if (!S_ISREG(tmp_inode->i_mode)) | ||
1083 | return; | ||
1084 | |||
1085 | /* | ||
1086 | * No sense invalidating pages for new inode | ||
1087 | * since we we have not started caching | ||
1088 | * readahead file data yet. | ||
1089 | */ | ||
1090 | if (isNewInode) | ||
1091 | return; | ||
1092 | |||
1093 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
1094 | (local_size == tmp_inode->i_size)) { | ||
1095 | cFYI(1, ("inode exists but unchanged")); | ||
1096 | } else { | ||
1097 | /* file may have changed on server */ | ||
1098 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
1099 | invalidate_remote_inode(tmp_inode); | ||
1100 | } | ||
1101 | } | ||
1102 | |||
1103 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | 1020 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) |
1104 | { | 1021 | { |
1105 | int rc = 0, tmprc; | 1022 | int rc = 0, tmprc; |
@@ -1108,6 +1025,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1108 | struct cifsTconInfo *pTcon; | 1025 | struct cifsTconInfo *pTcon; |
1109 | char *full_path = NULL; | 1026 | char *full_path = NULL; |
1110 | struct inode *newinode = NULL; | 1027 | struct inode *newinode = NULL; |
1028 | struct cifs_fattr fattr; | ||
1111 | 1029 | ||
1112 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); | 1030 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); |
1113 | 1031 | ||
@@ -1118,8 +1036,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1118 | 1036 | ||
1119 | full_path = build_path_from_dentry(direntry); | 1037 | full_path = build_path_from_dentry(direntry); |
1120 | if (full_path == NULL) { | 1038 | if (full_path == NULL) { |
1039 | rc = -ENOMEM; | ||
1121 | FreeXid(xid); | 1040 | FreeXid(xid); |
1122 | return -ENOMEM; | 1041 | return rc; |
1123 | } | 1042 | } |
1124 | 1043 | ||
1125 | if ((pTcon->ses->capabilities & CAP_UNIX) && | 1044 | if ((pTcon->ses->capabilities & CAP_UNIX) && |
@@ -1146,7 +1065,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1146 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 1065 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
1147 | d_drop(direntry); | 1066 | d_drop(direntry); |
1148 | } else { | 1067 | } else { |
1149 | __u64 unique_id; | ||
1150 | if (pInfo->Type == cpu_to_le32(-1)) { | 1068 | if (pInfo->Type == cpu_to_le32(-1)) { |
1151 | /* no return info, go query for it */ | 1069 | /* no return info, go query for it */ |
1152 | kfree(pInfo); | 1070 | kfree(pInfo); |
@@ -1160,20 +1078,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1160 | else | 1078 | else |
1161 | direntry->d_op = &cifs_dentry_ops; | 1079 | direntry->d_op = &cifs_dentry_ops; |
1162 | 1080 | ||
1163 | unique_id = le64_to_cpu(pInfo->UniqueId); | 1081 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
1164 | newinode = cifs_new_inode(inode->i_sb, &unique_id); | 1082 | newinode = cifs_iget(inode->i_sb, &fattr); |
1165 | if (newinode == NULL) { | 1083 | if (!newinode) { |
1166 | kfree(pInfo); | 1084 | kfree(pInfo); |
1167 | goto mkdir_get_info; | 1085 | goto mkdir_get_info; |
1168 | } | 1086 | } |
1169 | 1087 | ||
1170 | newinode->i_nlink = 2; | ||
1171 | d_instantiate(direntry, newinode); | 1088 | d_instantiate(direntry, newinode); |
1172 | 1089 | ||
1173 | /* we already checked in POSIXCreate whether | ||
1174 | frame was long enough */ | ||
1175 | posix_fill_in_inode(direntry->d_inode, | ||
1176 | pInfo, 1 /* NewInode */); | ||
1177 | #ifdef CONFIG_CIFS_DEBUG2 | 1090 | #ifdef CONFIG_CIFS_DEBUG2 |
1178 | cFYI(1, ("instantiated dentry %p %s to inode %p", | 1091 | cFYI(1, ("instantiated dentry %p %s to inode %p", |
1179 | direntry, direntry->d_name.name, newinode)); | 1092 | direntry, direntry->d_name.name, newinode)); |
@@ -1236,10 +1149,10 @@ mkdir_get_info: | |||
1236 | args.uid = NO_CHANGE_64; | 1149 | args.uid = NO_CHANGE_64; |
1237 | args.gid = NO_CHANGE_64; | 1150 | args.gid = NO_CHANGE_64; |
1238 | } | 1151 | } |
1239 | CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | 1152 | CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, |
1240 | cifs_sb->local_nls, | 1153 | cifs_sb->local_nls, |
1241 | cifs_sb->mnt_cifs_flags & | 1154 | cifs_sb->mnt_cifs_flags & |
1242 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1155 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1243 | } else { | 1156 | } else { |
1244 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | 1157 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && |
1245 | (mode & S_IWUGO) == 0) { | 1158 | (mode & S_IWUGO) == 0) { |
@@ -1303,8 +1216,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1303 | 1216 | ||
1304 | full_path = build_path_from_dentry(direntry); | 1217 | full_path = build_path_from_dentry(direntry); |
1305 | if (full_path == NULL) { | 1218 | if (full_path == NULL) { |
1219 | rc = -ENOMEM; | ||
1306 | FreeXid(xid); | 1220 | FreeXid(xid); |
1307 | return -ENOMEM; | 1221 | return rc; |
1308 | } | 1222 | } |
1309 | 1223 | ||
1310 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1224 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, |
@@ -1508,8 +1422,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
1508 | since that would deadlock */ | 1422 | since that would deadlock */ |
1509 | full_path = build_path_from_dentry(direntry); | 1423 | full_path = build_path_from_dentry(direntry); |
1510 | if (full_path == NULL) { | 1424 | if (full_path == NULL) { |
1425 | rc = -ENOMEM; | ||
1511 | FreeXid(xid); | 1426 | FreeXid(xid); |
1512 | return -ENOMEM; | 1427 | return rc; |
1513 | } | 1428 | } |
1514 | cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " | 1429 | cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " |
1515 | "jiffies %ld", full_path, direntry->d_inode, | 1430 | "jiffies %ld", full_path, direntry->d_inode, |
@@ -1618,6 +1533,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1618 | if (!err) { | 1533 | if (!err) { |
1619 | generic_fillattr(dentry->d_inode, stat); | 1534 | generic_fillattr(dentry->d_inode, stat); |
1620 | stat->blksize = CIFS_MAX_MSGSIZE; | 1535 | stat->blksize = CIFS_MAX_MSGSIZE; |
1536 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
1621 | } | 1537 | } |
1622 | return err; | 1538 | return err; |
1623 | } | 1539 | } |
@@ -1782,6 +1698,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1782 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1698 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1783 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1699 | struct cifsTconInfo *pTcon = cifs_sb->tcon; |
1784 | struct cifs_unix_set_info_args *args = NULL; | 1700 | struct cifs_unix_set_info_args *args = NULL; |
1701 | struct cifsFileInfo *open_file; | ||
1785 | 1702 | ||
1786 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", | 1703 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", |
1787 | direntry->d_name.name, attrs->ia_valid)); | 1704 | direntry->d_name.name, attrs->ia_valid)); |
@@ -1868,10 +1785,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1868 | args->ctime = NO_CHANGE_64; | 1785 | args->ctime = NO_CHANGE_64; |
1869 | 1786 | ||
1870 | args->device = 0; | 1787 | args->device = 0; |
1871 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, | 1788 | open_file = find_writable_file(cifsInode); |
1872 | cifs_sb->local_nls, | 1789 | if (open_file) { |
1873 | cifs_sb->mnt_cifs_flags & | 1790 | u16 nfid = open_file->netfid; |
1874 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1791 | u32 npid = open_file->pid; |
1792 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | ||
1793 | atomic_dec(&open_file->wrtPending); | ||
1794 | } else { | ||
1795 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | ||
1796 | cifs_sb->local_nls, | ||
1797 | cifs_sb->mnt_cifs_flags & | ||
1798 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1799 | } | ||
1875 | 1800 | ||
1876 | if (!rc) | 1801 | if (!rc) |
1877 | rc = inode_setattr(inode, attrs); | 1802 | rc = inode_setattr(inode, attrs); |
@@ -1911,8 +1836,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
1911 | 1836 | ||
1912 | full_path = build_path_from_dentry(direntry); | 1837 | full_path = build_path_from_dentry(direntry); |
1913 | if (full_path == NULL) { | 1838 | if (full_path == NULL) { |
1839 | rc = -ENOMEM; | ||
1914 | FreeXid(xid); | 1840 | FreeXid(xid); |
1915 | return -ENOMEM; | 1841 | return rc; |
1916 | } | 1842 | } |
1917 | 1843 | ||
1918 | /* | 1844 | /* |