diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 184 |
1 files changed, 94 insertions, 90 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e5210519ac4..8e86aaceb68 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -2,7 +2,7 @@ * fs/cifs/dir.c * * vfs operations that deal with dentries - * + * * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) * @@ -34,11 +34,12 @@ static void renew_parental_timestamps(struct dentry *direntry) { - /* BB check if there is a way to get the kernel to do this or if we really need this */ + /* BB check if there is a way to get the kernel to do this or if we + really need this */ do { direntry->d_time = jiffies; direntry = direntry->d_parent; - } while (!IS_ROOT(direntry)); + } while (!IS_ROOT(direntry)); } /* Note: caller must free return buffer */ @@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry) char *full_path; char dirsep; - if(direntry == NULL) + if (direntry == NULL) return NULL; /* not much we can do if dentry is freed and we need to reopen the file after it was closed implicitly when the server crashed */ @@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry) dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); pplen = CIFS_SB(direntry->d_sb)->prepathlen; cifs_bp_rename_retry: - namelen = pplen; + namelen = pplen; for (temp = direntry; !IS_ROOT(temp);) { namelen += (1 + temp->d_name.len); temp = temp->d_parent; - if(temp == NULL) { - cERROR(1,("corrupt dentry")); + if (temp == NULL) { + cERROR(1, ("corrupt dentry")); return NULL; } } full_path = kmalloc(namelen+1, GFP_KERNEL); - if(full_path == NULL) + if (full_path == NULL) return full_path; full_path[namelen] = 0; /* trailing null */ for (temp = direntry; !IS_ROOT(temp);) { @@ -84,8 +85,8 @@ cifs_bp_rename_retry: cFYI(0, ("name: %s", full_path + namelen)); } temp = temp->d_parent; - if(temp == NULL) { - cERROR(1,("corrupt dentry")); + if (temp == NULL) { + cERROR(1, ("corrupt dentry")); kfree(full_path); return NULL; } @@ -94,7 +95,7 @@ cifs_bp_rename_retry: cERROR(1, ("did not end path lookup where expected namelen is %d", namelen)); - /* presumably this is only possible if racing with a rename + /* presumably this is only possible if racing with a rename of one of the parent directories (we can not lock the dentries above us to prevent this, but retrying should be harmless) */ kfree(full_path); @@ -106,7 +107,7 @@ cifs_bp_rename_retry: since the '\' is a valid posix character so we can not switch those safely to '/' if any are found in the middle of the prepath */ /* BB test paths to Windows with '/' in the midst of prepath */ - strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen); + strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen); return full_path; } @@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); - if(full_path == NULL) { + if (full_path == NULL) { FreeXid(xid); return -ENOMEM; } - if(nd && (nd->flags & LOOKUP_OPEN)) { + if (nd && (nd->flags & LOOKUP_OPEN)) { int oflags = nd->intent.open.flags; desiredAccess = 0; @@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, write_only = TRUE; } - if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) disposition = FILE_CREATE; - else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) + else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) disposition = FILE_OVERWRITE_IF; - else if((oflags & O_CREAT) == O_CREAT) + else if ((oflags & O_CREAT) == O_CREAT) disposition = FILE_OPEN_IF; else { - cFYI(1,("Create flag not set in create function")); + cFYI(1, ("Create flag not set in create function")); } } - /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */ + /* BB add processing to set equivalent of mode - e.g. via CreateX with + ACLs */ if (oplockEnabled) oplock = REQ_OPLOCK; - buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); - if(buf == NULL) { + buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); + if (buf == NULL) { kfree(full_path); FreeXid(xid); return -ENOMEM; } - if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) + if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &fileHandle, &oplock, buf, cifs_sb->local_nls, @@ -193,27 +195,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, else rc = -EIO; /* no NT SMB support fall into legacy open below */ - if(rc == -EIO) { + if (rc == -EIO) { /* old server, retry the open legacy style */ rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &fileHandle, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } + } if (rc) { cFYI(1, ("cifs_create returned 0x%x", rc)); } else { /* If Open reported that we actually created a file then we now have to set the mode if possible */ if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && - (oplock & CIFS_CREATE_ACTION)) - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { + (oplock & CIFS_CREATE_ACTION)) { + mode &= ~current->fs->umask; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, (__u64)current->fsuid, (__u64)current->fsgid, 0 /* dev */, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, @@ -221,26 +224,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, (__u64)-1, 0 /* dev */, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } - else { - /* BB implement mode setting via Windows security descriptors */ - /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ - /* could set r/o dos attribute if mode & 0222 == 0 */ + } else { + /* BB implement mode setting via Windows security + descriptors e.g. */ + /* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/ + + /* Could set r/o dos attribute if mode & 0222 == 0 */ } /* BB server might mask mode so we have to query for Unix case*/ if (pTcon->ses->capabilities & CAP_UNIX) rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb,xid); + inode->i_sb, xid); else { rc = cifs_get_inode_info(&newinode, full_path, - buf, inode->i_sb,xid); - if(newinode) { + buf, inode->i_sb, xid); + if (newinode) { newinode->i_mode = mode; - if((oplock & CIFS_CREATE_ACTION) && - (cifs_sb->mnt_cifs_flags & + if ((oplock & CIFS_CREATE_ACTION) && + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { newinode->i_uid = current->fsuid; newinode->i_gid = current->fsgid; @@ -259,14 +264,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, direntry->d_op = &cifs_dentry_ops; d_instantiate(direntry, newinode); } - if((nd->flags & LOOKUP_OPEN) == FALSE) { + if ((nd->flags & LOOKUP_OPEN) == FALSE) { /* mknod case - do not leave file open */ CIFSSMBClose(xid, pTcon, fileHandle); - } else if(newinode) { + } else if (newinode) { pCifsFile = kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); - - if(pCifsFile == NULL) + + if (pCifsFile == NULL) goto cifs_create_out; pCifsFile->netfid = fileHandle; pCifsFile->pid = current->tgid; @@ -276,33 +281,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, init_MUTEX(&pCifsFile->fh_sem); mutex_init(&pCifsFile->lock_mutex); INIT_LIST_HEAD(&pCifsFile->llist); - atomic_set(&pCifsFile->wrtPending,0); + atomic_set(&pCifsFile->wrtPending, 0); - /* set the following in open now + /* set the following in open now pCifsFile->pfile = file; */ write_lock(&GlobalSMBSeslock); - list_add(&pCifsFile->tlist,&pTcon->openFileList); + list_add(&pCifsFile->tlist, &pTcon->openFileList); pCifsInode = CIFS_I(newinode); - if(pCifsInode) { + if (pCifsInode) { /* if readable file instance put first in list*/ if (write_only == TRUE) { - list_add_tail(&pCifsFile->flist, + list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); } else { list_add(&pCifsFile->flist, &pCifsInode->openFileList); } - if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { + if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheRead = TRUE; - cFYI(1,("Exclusive Oplock for inode %p", + cFYI(1, ("Exclusive Oplock inode %p", newinode)); - } else if((oplock & 0xF) == OPLOCK_READ) + } else if ((oplock & 0xF) == OPLOCK_READ) pCifsInode->clientCanCacheRead = TRUE; } write_unlock(&GlobalSMBSeslock); } - } + } cifs_create_out: kfree(buf); kfree(full_path); @@ -310,8 +315,8 @@ cifs_create_out: return rc; } -int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, - dev_t device_number) +int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, + dev_t device_number) { int rc = -EPERM; int xid; @@ -329,43 +334,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); - if(full_path == NULL) + if (full_path == NULL) rc = -ENOMEM; else if (pTcon->ses->capabilities & CAP_UNIX) { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { + mode &= ~current->fs->umask; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, - mode,(__u64)current->fsuid,(__u64)current->fsgid, + mode, (__u64)current->fsuid, + (__u64)current->fsgid, device_number, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else { rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, (__u64)-1, (__u64)-1, device_number, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } - if(!rc) { + if (!rc) { rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb,xid); + inode->i_sb, xid); if (pTcon->nocase) direntry->d_op = &cifs_ci_dentry_ops; else direntry->d_op = &cifs_dentry_ops; - if(rc == 0) + if (rc == 0) d_instantiate(direntry, newinode); } } else { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { int oplock = 0; u16 fileHandle; FILE_ALL_INFO * buf; - cFYI(1,("sfu compat create special file")); + cFYI(1, ("sfu compat create special file")); - buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); - if(buf == NULL) { + buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); + if (buf == NULL) { kfree(full_path); FreeXid(xid); return -ENOMEM; @@ -373,39 +380,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, /* fail if exists */ - GENERIC_WRITE /* BB would + GENERIC_WRITE /* BB would WRITE_OWNER | WRITE_DAC be better? */, /* Create a file and set the file attribute to SYSTEM */ CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, &fileHandle, &oplock, buf, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* BB FIXME - add handling for backlevel servers which need legacy open and check for all - calls to SMBOpen for fallback to - SMBLeagcyOpen */ - if(!rc) { + calls to SMBOpen for fallback to SMBLeagcyOpen */ + if (!rc) { /* BB Do not bother to decode buf since no local inode yet to put timestamps in, but we can reuse it safely */ int bytes_written; struct win_dev *pdev; pdev = (struct win_dev *)buf; - if(S_ISCHR(mode)) { + if (S_ISCHR(mode)) { memcpy(pdev->type, "IntxCHR", 8); pdev->major = cpu_to_le64(MAJOR(device_number)); - pdev->minor = + pdev->minor = cpu_to_le64(MINOR(device_number)); rc = CIFSSMBWrite(xid, pTcon, fileHandle, sizeof(struct win_dev), 0, &bytes_written, (char *)pdev, NULL, 0); - } else if(S_ISBLK(mode)) { + } else if (S_ISBLK(mode)) { memcpy(pdev->type, "IntxBLK", 8); pdev->major = cpu_to_le64(MAJOR(device_number)); @@ -432,7 +438,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, struct dentry * -cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd) +cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, + struct nameidata *nd) { int xid; int rc = 0; /* to get around spurious gcc warning, set to zero here */ @@ -447,8 +454,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name (" parent inode = 0x%p name is: %s and dentry = 0x%p", parent_dir_inode, direntry->d_name.name, direntry)); - /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */ - /* check whether path exists */ cifs_sb = CIFS_SB(parent_dir_inode->i_sb); @@ -472,7 +477,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name deadlock in the cases (beginning of sys_rename itself) in which we already have the sb rename sem */ full_path = build_path_from_dentry(direntry); - if(full_path == NULL) { + if (full_path == NULL) { FreeXid(xid); return ERR_PTR(-ENOMEM); } @@ -487,10 +492,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name if (pTcon->ses->capabilities & CAP_UNIX) rc = cifs_get_inode_info_unix(&newInode, full_path, - parent_dir_inode->i_sb,xid); + parent_dir_inode->i_sb, xid); else rc = cifs_get_inode_info(&newInode, full_path, NULL, - parent_dir_inode->i_sb,xid); + parent_dir_inode->i_sb, xid); if ((rc == 0) && (newInode != NULL)) { if (pTcon->nocase) @@ -499,7 +504,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name direntry->d_op = &cifs_dentry_ops; d_add(direntry, newInode); - /* since paths are not looked up by component - the parent + /* since paths are not looked up by component - the parent directories are presumed to be good here */ renew_parental_timestamps(direntry); @@ -511,13 +516,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name else direntry->d_op = &cifs_dentry_ops; d_add(direntry, NULL); - /* if it was once a directory (but how can we tell?) we could do - shrink_dcache_parent(direntry); */ + /* if it was once a directory (but how can we tell?) we could do + shrink_dcache_parent(direntry); */ } else { - cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", - rc,full_path)); - /* BB special case check for Access Denied - watch security - exposure of returning dir info implicitly via different rc + cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s", + rc, full_path)); + /* BB special case check for Access Denied - watch security + exposure of returning dir info implicitly via different rc if file exists or not but no access BB */ } @@ -538,11 +543,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) } else { cFYI(1, ("neg dentry 0x%p name = %s", direntry, direntry->d_name.name)); - if(time_after(jiffies, direntry->d_time + HZ) || + if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled) { d_drop(direntry); isValid = 0; - } + } } return isValid; @@ -559,8 +564,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) struct dentry_operations cifs_dentry_ops = { .d_revalidate = cifs_d_revalidate, -/* d_delete: cifs_d_delete, *//* not needed except for debugging */ - /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ +/* d_delete: cifs_d_delete, */ /* not needed except for debugging */ }; static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) |