aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c189
1 files changed, 54 insertions, 135 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f54e1866f0f4..e3137aa48cdd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -101,68 +101,15 @@ cifs_bp_rename_retry:
101 return full_path; 101 return full_path;
102} 102}
103 103
104/* Note: caller must free return buffer */ 104/* char * build_wildcard_path_from_dentry(struct dentry *direntry)
105char *
106build_wildcard_path_from_dentry(struct dentry *direntry)
107{ 105{
108 struct dentry *temp;
109 int namelen = 0;
110 char *full_path;
111
112 if(direntry == NULL)
113 return NULL; /* not much we can do if dentry is freed and
114 we need to reopen the file after it was closed implicitly
115 when the server crashed */
116
117cifs_bwp_rename_retry:
118 for (temp = direntry; !IS_ROOT(temp);) {
119 namelen += (1 + temp->d_name.len);
120 temp = temp->d_parent;
121 if(temp == NULL) {
122 cERROR(1,("corrupt dentry"));
123 return NULL;
124 }
125 }
126
127 full_path = kmalloc(namelen+3, GFP_KERNEL);
128 if(full_path == NULL) 106 if(full_path == NULL)
129 return full_path; 107 return full_path;
130 108
131 full_path[namelen] = '\\'; 109 full_path[namelen] = '\\';
132 full_path[namelen+1] = '*'; 110 full_path[namelen+1] = '*';
133 full_path[namelen+2] = 0; /* trailing null */ 111 full_path[namelen+2] = 0;
134 112BB remove above eight lines BB */
135 for (temp = direntry; !IS_ROOT(temp);) {
136 namelen -= 1 + temp->d_name.len;
137 if (namelen < 0) {
138 break;
139 } else {
140 full_path[namelen] = '\\';
141 strncpy(full_path + namelen + 1, temp->d_name.name,
142 temp->d_name.len);
143 cFYI(0, (" name: %s ", full_path + namelen));
144 }
145 temp = temp->d_parent;
146 if(temp == NULL) {
147 cERROR(1,("corrupt dentry"));
148 kfree(full_path);
149 return NULL;
150 }
151 }
152 if (namelen != 0) {
153 cERROR(1,
154 ("We did not end path lookup where we expected namelen is %d",
155 namelen));
156 /* presumably this is only possible if we were racing with a rename
157 of one of the parent directories (we can not lock the dentries
158 above us to prevent this, but retrying should be harmless) */
159 kfree(full_path);
160 namelen = 0;
161 goto cifs_bwp_rename_retry;
162 }
163
164 return full_path;
165}
166 113
167/* Inode operations in similar order to how they appear in the Linux file fs.h */ 114/* Inode operations in similar order to how they appear in the Linux file fs.h */
168 115
@@ -235,7 +182,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
235 182
236 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 183 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
237 desiredAccess, CREATE_NOT_DIR, 184 desiredAccess, CREATE_NOT_DIR,
238 &fileHandle, &oplock, buf, cifs_sb->local_nls); 185 &fileHandle, &oplock, buf, cifs_sb->local_nls,
186 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
239 if (rc) { 187 if (rc) {
240 cFYI(1, ("cifs_create returned 0x%x ", rc)); 188 cFYI(1, ("cifs_create returned 0x%x ", rc));
241 } else { 189 } else {
@@ -248,13 +196,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
248 (__u64)current->euid, 196 (__u64)current->euid,
249 (__u64)current->egid, 197 (__u64)current->egid,
250 0 /* dev */, 198 0 /* dev */,
251 cifs_sb->local_nls); 199 cifs_sb->local_nls,
200 cifs_sb->mnt_cifs_flags &
201 CIFS_MOUNT_MAP_SPECIAL_CHR);
252 } else { 202 } else {
253 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 203 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
254 (__u64)-1, 204 (__u64)-1,
255 (__u64)-1, 205 (__u64)-1,
256 0 /* dev */, 206 0 /* dev */,
257 cifs_sb->local_nls); 207 cifs_sb->local_nls,
208 cifs_sb->mnt_cifs_flags &
209 CIFS_MOUNT_MAP_SPECIAL_CHR);
258 } 210 }
259 else { 211 else {
260 /* BB implement via Windows security descriptors */ 212 /* BB implement via Windows security descriptors */
@@ -284,51 +236,48 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
284 /* mknod case - do not leave file open */ 236 /* mknod case - do not leave file open */
285 CIFSSMBClose(xid, pTcon, fileHandle); 237 CIFSSMBClose(xid, pTcon, fileHandle);
286 } else if(newinode) { 238 } else if(newinode) {
287 pCifsFile = (struct cifsFileInfo *) 239 pCifsFile =
288 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); 240 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
289 241
290 if (pCifsFile) { 242 if(pCifsFile == NULL)
291 memset((char *)pCifsFile, 0, 243 goto cifs_create_out;
292 sizeof (struct cifsFileInfo)); 244 memset((char *)pCifsFile, 0,
293 pCifsFile->netfid = fileHandle; 245 sizeof (struct cifsFileInfo));
294 pCifsFile->pid = current->tgid; 246 pCifsFile->netfid = fileHandle;
295 pCifsFile->pInode = newinode; 247 pCifsFile->pid = current->tgid;
296 pCifsFile->invalidHandle = FALSE; 248 pCifsFile->pInode = newinode;
297 pCifsFile->closePend = FALSE; 249 pCifsFile->invalidHandle = FALSE;
298 init_MUTEX(&pCifsFile->fh_sem); 250 pCifsFile->closePend = FALSE;
299 /* put the following in at open now */ 251 init_MUTEX(&pCifsFile->fh_sem);
300 /* pCifsFile->pfile = file; */ 252 /* set the following in open now
301 write_lock(&GlobalSMBSeslock); 253 pCifsFile->pfile = file; */
302 list_add(&pCifsFile->tlist,&pTcon->openFileList); 254 write_lock(&GlobalSMBSeslock);
303 pCifsInode = CIFS_I(newinode); 255 list_add(&pCifsFile->tlist,&pTcon->openFileList);
304 if(pCifsInode) { 256 pCifsInode = CIFS_I(newinode);
257 if(pCifsInode) {
305 /* if readable file instance put first in list*/ 258 /* if readable file instance put first in list*/
306 if (write_only == TRUE) { 259 if (write_only == TRUE) {
307 list_add_tail(&pCifsFile->flist, 260 list_add_tail(&pCifsFile->flist,
308 &pCifsInode->openFileList); 261 &pCifsInode->openFileList);
309 } else { 262 } else {
310 list_add(&pCifsFile->flist, 263 list_add(&pCifsFile->flist,
311 &pCifsInode->openFileList); 264 &pCifsInode->openFileList);
312 }
313 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
314 pCifsInode->clientCanCacheAll = TRUE;
315 pCifsInode->clientCanCacheRead = TRUE;
316 cFYI(1,("Exclusive Oplock granted on inode %p",
317 newinode));
318 } else if((oplock & 0xF) == OPLOCK_READ)
319 pCifsInode->clientCanCacheRead = TRUE;
320 } 265 }
321 write_unlock(&GlobalSMBSeslock); 266 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
267 pCifsInode->clientCanCacheAll = TRUE;
268 pCifsInode->clientCanCacheRead = TRUE;
269 cFYI(1,("Exclusive Oplock for inode %p",
270 newinode));
271 } else if((oplock & 0xF) == OPLOCK_READ)
272 pCifsInode->clientCanCacheRead = TRUE;
322 } 273 }
274 write_unlock(&GlobalSMBSeslock);
323 } 275 }
324 } 276 }
325 277cifs_create_out:
326 if (buf) 278 kfree(buf);
327 kfree(buf); 279 kfree(full_path);
328 if (full_path)
329 kfree(full_path);
330 FreeXid(xid); 280 FreeXid(xid);
331
332 return rc; 281 return rc;
333} 282}
334 283
@@ -359,11 +308,15 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
359 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 308 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
360 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 309 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
361 mode,(__u64)current->euid,(__u64)current->egid, 310 mode,(__u64)current->euid,(__u64)current->egid,
362 device_number, cifs_sb->local_nls); 311 device_number, cifs_sb->local_nls,
312 cifs_sb->mnt_cifs_flags &
313 CIFS_MOUNT_MAP_SPECIAL_CHR);
363 } else { 314 } else {
364 rc = CIFSSMBUnixSetPerms(xid, pTcon, 315 rc = CIFSSMBUnixSetPerms(xid, pTcon,
365 full_path, mode, (__u64)-1, (__u64)-1, 316 full_path, mode, (__u64)-1, (__u64)-1,
366 device_number, cifs_sb->local_nls); 317 device_number, cifs_sb->local_nls,
318 cifs_sb->mnt_cifs_flags &
319 CIFS_MOUNT_MAP_SPECIAL_CHR);
367 } 320 }
368 321
369 if(!rc) { 322 if(!rc) {
@@ -375,10 +328,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
375 } 328 }
376 } 329 }
377 330
378 if (full_path) 331 kfree(full_path);
379 kfree(full_path);
380 FreeXid(xid); 332 FreeXid(xid);
381
382 return rc; 333 return rc;
383} 334}
384 335
@@ -447,43 +398,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
447 if file exists or not but no access BB */ 398 if file exists or not but no access BB */
448 } 399 }
449 400
450 if (full_path) 401 kfree(full_path);
451 kfree(full_path);
452 FreeXid(xid); 402 FreeXid(xid);
453 return ERR_PTR(rc); 403 return ERR_PTR(rc);
454} 404}
455 405
456int
457cifs_dir_open(struct inode *inode, struct file *file)
458{ /* NB: currently unused since searches are opened in readdir */
459 int rc = 0;
460 int xid;
461 struct cifs_sb_info *cifs_sb;
462 struct cifsTconInfo *pTcon;
463 char *full_path = NULL;
464
465 xid = GetXid();
466
467 cifs_sb = CIFS_SB(inode->i_sb);
468 pTcon = cifs_sb->tcon;
469
470 if(file->f_dentry) {
471 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
472 full_path = build_wildcard_path_from_dentry(file->f_dentry);
473 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
474 } else {
475 FreeXid(xid);
476 return -EIO;
477 }
478
479 cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
480
481 if (full_path)
482 kfree(full_path);
483 FreeXid(xid);
484 return rc;
485}
486
487static int 406static int
488cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) 407cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
489{ 408{