if (tmp_path == NULL) {
return -ENOMEM;
}
- /* have to skip first of the double backslash of
+ /* have to skip first of the double backslash of
UNC name */
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
strncat(tmp_path, search_path, MAX_PATHCONF);
rc = connect_to_dfs_path(xid, pTcon->ses,
/* treename + */ tmp_path,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
kfree(tmp_path);
/* get new inode */
if (*pinode == NULL) {
*pinode = new_inode(sb);
- if (*pinode == NULL)
+ if (*pinode == NULL)
return -ENOMEM;
/* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that
} /* note ino incremented to unique num in new_inode */
if (sb->s_flags & MS_NOATIME)
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
-
+
insert_inode_hash(*pinode);
}
cifsInfo->time = jiffies;
cFYI(1, ("New time %ld", cifsInfo->time));
/* this is ok to set on every inode revalidate */
- atomic_set(&cifsInfo->inUse,1);
+ atomic_set(&cifsInfo->inUse, 1);
inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
inode->i_mode = le64_to_cpu(findData.Permissions);
/* since we set the inode type below we need to mask off
- to avoid strange results if bits set above */
- inode->i_mode &= ~S_IFMT;
+ to avoid strange results if bits set above */
+ inode->i_mode &= ~S_IFMT;
if (type == UNIX_FILE) {
inode->i_mode |= S_IFREG;
} else if (type == UNIX_SYMLINK) {
} else {
/* safest to call it a file if we do not know */
inode->i_mode |= S_IFREG;
- cFYI(1,("unknown type %d",type));
+ cFYI(1, ("unknown type %d", type));
}
-
+
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
inode->i_uid = cifs_sb->mnt_uid;
else
inode->i_gid = cifs_sb->mnt_gid;
else
inode->i_gid = le64_to_cpu(findData.Gid);
-
+
inode->i_nlink = le64_to_cpu(findData.Nlinks);
spin_lock(&inode->i_lock);
inode->i_op = &cifs_file_inode_ops;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- inode->i_fop =
+ inode->i_fop =
&cifs_file_direct_nobrl_ops;
else
inode->i_fop = &cifs_file_direct_ops;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
inode->i_fop = &cifs_file_nobrl_ops;
- else /* not direct, send byte range locks */
+ else /* not direct, send byte range locks */
inode->i_fop = &cifs_file_ops;
/* check if server can support readpages */
- if (pTcon->ses->server->maxBuf <
+ if (pTcon->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else
return rc;
}
-static int decode_sfu_inode(struct inode * inode, __u64 size,
+static int decode_sfu_inode(struct inode *inode, __u64 size,
const unsigned char *path,
struct cifs_sb_info *cifs_sb, int xid)
{
struct cifsTconInfo *pTcon = cifs_sb->tcon;
char buf[24];
unsigned int bytes_read;
- char * pbuf;
+ char *pbuf;
pbuf = buf;
} else if (size < 8) {
return -EINVAL; /* EOPNOTSUPP? */
}
-
+
rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR, &netfid, &oplock, NULL,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc==0) {
+ if (rc == 0) {
int buf_type = CIFS_NO_BUFFER;
/* Read header */
rc = CIFSSMBRead(xid, pTcon,
- netfid,
+ netfid,
24 /* length */, 0 /* offset */,
&bytes_read, &pbuf, &buf_type);
if ((rc == 0) && (bytes_read >= 8)) {
if (memcmp("IntxBLK", pbuf, 8) == 0) {
- cFYI(1,("Block device"));
+ cFYI(1, ("Block device"));
inode->i_mode |= S_IFBLK;
if (bytes_read == 24) {
/* we have enough to decode dev num */
inode->i_rdev = MKDEV(mjr, mnr);
}
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
- cFYI(1,("Char device"));
+ cFYI(1, ("Char device"));
inode->i_mode |= S_IFCHR;
if (bytes_read == 24) {
/* we have enough to decode dev num */
mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
inode->i_rdev = MKDEV(mjr, mnr);
- }
+ }
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
- cFYI(1,("Symlink"));
+ cFYI(1, ("Symlink"));
inode->i_mode |= S_IFLNK;
} else {
inode->i_mode |= S_IFREG; /* file? */
- rc = -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
}
} else {
inode->i_mode |= S_IFREG; /* then it is a file */
- rc = -EOPNOTSUPP; /* or some unknown SFU type */
- }
+ rc = -EOPNOTSUPP; /* or some unknown SFU type */
+ }
CIFSSMBClose(xid, pTcon, netfid);
}
return rc;
-
}
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
-static int get_sfu_uid_mode(struct inode * inode,
+static int get_sfu_uid_mode(struct inode *inode,
const unsigned char *path,
struct cifs_sb_info *cifs_sb, int xid)
{
rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
ea_value, 4 /* size of buf */, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc < 0)
return (int)rc;
else if (rc > 3) {
mode = le32_to_cpu(*((__le32 *)ea_value));
- inode->i_mode &= ~SFBITS_MASK;
- cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
+ inode->i_mode &= ~SFBITS_MASK;
+ cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode));
inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
- cFYI(1,("special mode bits 0%o", mode));
+ cFYI(1, ("special mode bits 0%o", mode));
return 0;
} else {
return 0;
#else
return -EOPNOTSUPP;
#endif
-
-
}
int cifs_get_inode_info(struct inode **pinode,
int adjustTZ = FALSE;
pTcon = cifs_sb->tcon;
- cFYI(1,("Getting info on %s", search_path));
+ cFYI(1, ("Getting info on %s", search_path));
if ((pfindData == NULL) && (*pinode != NULL)) {
if (CIFS_I(*pinode)->clientCanCacheRead) {
- cFYI(1,("No need to revalidate cached inode sizes"));
+ cFYI(1, ("No need to revalidate cached inode sizes"));
return rc;
}
}
failed at least once - set flag in tcon or mount */
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
rc = SMBQueryInformation(xid, pTcon, search_path,
- pfindData, cifs_sb->local_nls,
+ pfindData, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
adjustTZ = TRUE;
}
-
}
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
if (rc) {
strncat(tmp_path, search_path, MAX_PATHCONF);
rc = connect_to_dfs_path(xid, pTcon->ses,
/* treename + */ tmp_path,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
kfree(tmp_path);
/* BB fix up inode etc. */
there Windows server or network appliances for which
IndexNumber field is not guaranteed unique? */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
int rc1 = 0;
__u64 inode_num;
- rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
- search_path, &inode_num,
+ rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
+ search_path, &inode_num,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc1) {
- cFYI(1,("GetSrvInodeNum rc %d", rc1));
+ cFYI(1, ("GetSrvInodeNum rc %d", rc1));
/* BB EOPNOSUPP disable SERVER_INUM? */
} else /* do we need cast or hash to ino? */
(*pinode)->i_ino = inode_num;
cFYI(0, ("Attributes came in as 0x%x", attr));
if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
- inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
+ inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
}
/* set default mode. will override for dirs below */
/* new inode, can safely set these fields */
inode->i_mode = cifs_sb->mnt_file_mode;
else /* since we set the inode type below we need to mask off
- to avoid strange results if type changes and both get orred in */
- inode->i_mode &= ~S_IFMT;
+ to avoid strange results if type changes and both
+ get orred in */
+ inode->i_mode &= ~S_IFMT;
/* if (attr & ATTR_REPARSE) */
/* We no longer handle these as symlinks because we could not
follow them due to the absolute path with drive letter */
/* BB Finish for SFU style symlinks and devices */
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
(cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
- if (decode_sfu_inode(inode,
+ if (decode_sfu_inode(inode,
le64_to_cpu(pfindData->EndOfFile),
search_path,
cifs_sb, xid)) {
- cFYI(1,("Unrecognized sfu inode type"));
+ cFYI(1, ("Unrecognized sfu inode type"));
}
- cFYI(1,("sfu mode 0%o",inode->i_mode));
+ cFYI(1, ("sfu mode 0%o", inode->i_mode));
} else {
inode->i_mode |= S_IFREG;
/* treat the dos attribute of read-only as read-only
/* BB add code here -
validate if device or weird share or device type? */
}
-
+
spin_lock(&inode->i_lock);
if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
/* can not safely shrink the file size here if the
client is writing to it due to potential races */
- i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
+ i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
/* 512 bytes (2**9) is the fake blocksize that must be
used for this calculation */
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
- /* BB fill in uid and gid here? with help from winbind?
+ /* BB fill in uid and gid here? with help from winbind?
or retrieve from NTFS stream extended attribute */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
/* fill in uid, gid, mode from server ACL */
inode->i_gid = cifs_sb->mnt_gid;
/* set so we do not keep refreshing these fields with
bad data after user has changed them in memory */
- atomic_set(&cifsInfo->inUse,1);
+ atomic_set(&cifsInfo->inUse, 1);
}
if (S_ISREG(inode->i_mode)) {
else /* not direct, send byte range locks */
inode->i_fop = &cifs_file_ops;
- if (pTcon->ses->server->maxBuf <
+ if (pTcon->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else
return rc;
}
+static const struct inode_operations cifs_ipc_inode_ops = {
+ .lookup = cifs_lookup,
+};
+
/* gets root inode */
void cifs_read_inode(struct inode *inode)
{
- int xid;
+ int xid, rc;
struct cifs_sb_info *cifs_sb;
cifs_sb = CIFS_SB(inode->i_sb);
xid = GetXid();
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
- cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
+
+ if (cifs_sb->tcon->unix_ext)
+ rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
else
- cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
+ rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
+ if (rc && cifs_sb->tcon->ipc) {
+ cFYI(1, ("ipc connection - fake read inode"));
+ inode->i_mode |= S_IFDIR;
+ inode->i_nlink = 2;
+ inode->i_op = &cifs_ipc_inode_ops;
+ inode->i_fop = &simple_dir_operations;
+ inode->i_uid = cifs_sb->mnt_uid;
+ inode->i_gid = cifs_sb->mnt_gid;
+ }
+
/* can not call macro FreeXid here since in a void func */
_FreeXid(xid);
}
FreeXid(xid);
return -ENOMEM;
}
- rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
+
+ if ((pTcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
+ rc = CIFSPOSIXDelFile(xid, pTcon, full_path,
+ SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+ cFYI(1, ("posix del rc %d", rc));
+ if ((rc == 0) || (rc == -ENOENT))
+ goto psx_del_no_retry;
+ }
+ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+psx_del_no_retry:
if (!rc) {
if (direntry->d_inode)
drop_nlink(direntry->d_inode);
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, NULL, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc==0) {
+ if (rc == 0) {
CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid);
if (direntry->d_inode)
rc = CIFSSMBSetTimes(xid, pTcon, full_path,
pinfo_buf,
cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
else
rc = -EOPNOTSUPP;
/* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
full_path,
(__u16)ATTR_NORMAL,
- cifs_sb->local_nls);
+ cifs_sb->local_nls);
For some strange reason it seems that NT4 eats the
old setattr call without actually setting the
attributes so on to the third attempted workaround
FILE_WRITE_ATTRIBUTES, 0,
&netfid, &oplock, NULL,
cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc==0) {
+ if (rc == 0) {
rc = CIFSSMBSetFileTimes(xid, pTcon,
pinfo_buf,
netfid);
}
kfree(pinfo_buf);
}
- if (rc==0) {
- rc = CIFSSMBDelFile(xid, pTcon, full_path,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ if (rc == 0) {
+ rc = CIFSSMBDelFile(xid, pTcon, full_path,
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
if (direntry->d_inode)
CREATE_NOT_DIR |
CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, NULL,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc==0) {
+ if (rc == 0) {
CIFSSMBRenameOpenFile(xid, pTcon,
netfid, NULL,
cifs_sb->local_nls,
tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
/* since we set the inode type below we need to mask off type
- to avoid strange results if bits above were corrupt */
- tmp_inode->i_mode &= ~S_IFMT;
+ to avoid strange results if bits above were corrupt */
+ tmp_inode->i_mode &= ~S_IFMT;
if (type == UNIX_FILE) {
*pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG;
/* safest to just call it a file */
*pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG;
- cFYI(1,("unknown inode type %d",type));
+ cFYI(1, ("unknown inode type %d", type));
}
#ifdef CONFIG_CIFS_DEBUG2
- cFYI(1,("object type: %d", type));
+ cFYI(1, ("object type: %d", type));
#endif
tmp_inode->i_uid = le64_to_cpu(pData->Uid);
tmp_inode->i_gid = le64_to_cpu(pData->Gid);
spin_lock(&tmp_inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
- /* can not safely change the file size here if the
+ /* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write(tmp_inode, end_of_file);
cFYI(1, ("File inode"));
tmp_inode->i_op = &cifs_file_inode_ops;
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
else
tmp_inode->i_fop = &cifs_file_direct_ops;
-
- } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+
+ } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
tmp_inode->i_fop = &cifs_file_nobrl_ops;
else
tmp_inode->i_fop = &cifs_file_ops;
- if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
- (cifs_sb->tcon->ses->server->maxBuf <
+ if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
+ (cifs_sb->tcon->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else
tmp_inode->i_data.a_ops = &cifs_addr_ops;
- if(isNewInode)
- return; /* No sense invalidating pages for new inode since we
- have not started caching readahead file data yet */
+ if (isNewInode)
+ return; /* No sense invalidating pages for new inode
+ since we we have not started caching
+ readahead file data yet */
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
(local_size == tmp_inode->i_size)) {
tmp_inode->i_op = &cifs_symlink_inode_ops;
/* tmp_inode->i_fop = *//* do not need to set to anything */
} else {
- cFYI(1, ("Special inode"));
+ cFYI(1, ("Special inode"));
init_special_inode(tmp_inode, tmp_inode->i_mode,
tmp_inode->i_rdev);
- }
+ }
}
int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
FreeXid(xid);
return -ENOMEM;
}
-
- if((pTcon->ses->capabilities & CAP_UNIX) &&
- (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+
+ if ((pTcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
u32 oplock = 0;
- FILE_UNIX_BASIC_INFO * pInfo =
+ FILE_UNIX_BASIC_INFO * pInfo =
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
- if(pInfo == NULL) {
+ if (pInfo == NULL) {
rc = -ENOMEM;
goto mkdir_out;
}
-
+
+ mode &= ~current->fs->umask;
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
mode, NULL /* netfid */, pInfo, &oplock,
- full_path, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ full_path, cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc) {
+ if (rc == -EOPNOTSUPP) {
+ kfree(pInfo);
+ goto mkdir_retry_old;
+ } else if (rc) {
cFYI(1, ("posix mkdir returned 0x%x", rc));
d_drop(direntry);
} else {
int obj_type;
- if (pInfo->Type == -1) /* no return info - go query */
- goto mkdir_get_info;
-/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */
+ if (pInfo->Type == cpu_to_le32(-1)) {
+ /* no return info, go query for it */
+ kfree(pInfo);
+ goto mkdir_get_info;
+ }
+/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
+ to set uid/gid */
inc_nlink(inode);
if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops;
direntry->d_op = &cifs_dentry_ops;
newinode = new_inode(inode->i_sb);
- if (newinode == NULL)
+ if (newinode == NULL) {
+ kfree(pInfo);
goto mkdir_get_info;
+ }
/* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that
the server is really filling in that field? */
newinode->i_ino =
(unsigned long)pInfo->UniqueId;
} /* note ino incremented to unique num in new_inode */
- if(inode->i_sb->s_flags & MS_NOATIME)
+ if (inode->i_sb->s_flags & MS_NOATIME)
newinode->i_flags |= S_NOATIME | S_NOCMTIME;
newinode->i_nlink = 2;
posix_fill_in_inode(direntry->d_inode,
pInfo, &obj_type, 1 /* NewInode */);
#ifdef CONFIG_CIFS_DEBUG2
- cFYI(1,("instantiated dentry %p %s to inode %p",
+ cFYI(1, ("instantiated dentry %p %s to inode %p",
direntry, direntry->d_name.name, newinode));
- if(newinode->i_nlink != 2)
- cFYI(1,("unexpected number of links %d",
+ if (newinode->i_nlink != 2)
+ cFYI(1, ("unexpected number of links %d",
newinode->i_nlink));
#endif
}
kfree(pInfo);
goto mkdir_out;
- }
-
+ }
+mkdir_retry_old:
/* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("cifs_mkdir returned 0x%x", rc));
d_drop(direntry);
} else {
-mkdir_get_info:
+mkdir_get_info:
inc_nlink(inode);
- if (pTcon->ses->capabilities & CAP_UNIX)
+ if (pTcon->unix_ext)
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, NULL,
- inode->i_sb,xid);
+ inode->i_sb, xid);
if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops;
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
/* setting nlink not necessary except in cases where we
- * failed to get it from the server or was set bogus */
+ * failed to get it from the server or was set bogus */
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
- direntry->d_inode->i_nlink = 2;
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ direntry->d_inode->i_nlink = 2;
+ if (pTcon->unix_ext) {
+ mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode,
mode, (__u64)-1,
(__u64)-1, 0 /* dev_t */,
cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
}
- else {
+ } else {
/* BB to be implemented via Windows secrty descriptors
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
-1, -1, local_nls); */
- if(direntry->d_inode) {
+ if (direntry->d_inode) {
direntry->d_inode->i_mode = mode;
direntry->d_inode->i_mode |= S_IFDIR;
- if(cifs_sb->mnt_cifs_flags &
+ if (cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_SET_UID) {
- direntry->d_inode->i_uid =
+ direntry->d_inode->i_uid =
current->fsuid;
- direntry->d_inode->i_gid =
+ direntry->d_inode->i_gid =
current->fsgid;
}
}
}
}
-mkdir_out:
+mkdir_out:
kfree(full_path);
FreeXid(xid);
return rc;
if (!rc) {
drop_nlink(inode);
spin_lock(&direntry->d_inode->i_lock);
- i_size_write(direntry->d_inode,0);
+ i_size_write(direntry->d_inode, 0);
clear_nlink(direntry->d_inode);
spin_unlock(&direntry->d_inode->i_lock);
}
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
if (info_buf_source != NULL) {
info_buf_target = info_buf_source + 1;
- if (pTcon->ses->capabilities & CAP_UNIX)
+ if (pTcon->unix_ext)
rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
- info_buf_source,
+ info_buf_source,
cifs_sb_source->local_nls,
cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
might not right be right access to request */
rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR, &netfid, &oplock, NULL,
- cifs_sb_source->local_nls,
- cifs_sb_source->mnt_cifs_flags &
+ cifs_sb_source->local_nls,
+ cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc==0) {
+ if (rc == 0) {
rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
- cifs_sb_source->local_nls,
+ cifs_sb_source->local_nls,
cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid);
local_mtime = direntry->d_inode->i_mtime;
local_size = direntry->d_inode->i_size;
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+ if (cifs_sb->tcon->unix_ext) {
rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
- direntry->d_sb,xid);
+ direntry->d_sb, xid);
if (rc) {
cFYI(1, ("error on getting revalidate info %d", rc));
/* if (rc != -ENOENT)
}
} else {
rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
- direntry->d_sb,xid);
+ direntry->d_sb, xid);
if (rc) {
cFYI(1, ("error on getting revalidate info %d", rc));
/* if (rc != -ENOENT)
/* if not oplocked, we invalidate inode pages if mtime or file size
had changed on server */
- if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
+ if (timespec_equal(&local_mtime, &direntry->d_inode->i_mtime) &&
(local_size == direntry->d_inode->i_size)) {
cFYI(1, ("cifs_revalidate - inode unchanged"));
} else {
if (invalidate_inode) {
/* shrink_dcache not necessary now that cifs dentry ops
are exported for negative dentries */
-/* if(S_ISDIR(direntry->d_inode->i_mode))
+/* if (S_ISDIR(direntry->d_inode->i_mode))
shrink_dcache_parent(direntry); */
if (S_ISREG(direntry->d_inode->i_mode)) {
if (direntry->d_inode->i_mapping)
}
}
/* mutex_unlock(&direntry->d_inode->i_mutex); */
-
+
kfree(full_path);
FreeXid(xid);
return rc;
pgoff_t index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE - 1);
struct page *page;
- char *kaddr;
int rc = 0;
page = grab_cache_page(mapping, index);
if (!page)
return -ENOMEM;
- kaddr = kmap_atomic(page, KM_USER0);
- memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
- flush_dcache_page(page);
- kunmap_atomic(kaddr, KM_USER0);
+ zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
unlock_page(page);
page_cache_release(page);
return rc;
}
-static int cifs_vmtruncate(struct inode * inode, loff_t offset)
+static int cifs_vmtruncate(struct inode *inode, loff_t offset)
{
struct address_space *mapping = inode->i_mapping;
unsigned long limit;
}
i_size_write(inode, offset);
spin_unlock(&inode->i_lock);
+ /*
+ * unmap_mapping_range is called twice, first simply for efficiency
+ * so that truncate_inode_pages does fewer single-page unmaps. However
+ * after this first call, and before truncate_inode_pages finishes,
+ * it is possible for private pages to be COWed, which remain after
+ * truncate_inode_pages finishes, hence the second unmap_mapping_range
+ * call must be made for correctness.
+ */
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
truncate_inode_pages(mapping, offset);
+ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
goto out_truncate;
do_expand:
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
/* check if we have permission to change attrs */
rc = inode_change_ok(direntry->d_inode, attrs);
- if(rc < 0) {
+ if (rc < 0) {
FreeXid(xid);
return rc;
} else
rc = 0;
}
-
+
full_path = build_path_from_dentry(direntry);
if (full_path == NULL) {
FreeXid(xid);
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
nfid, npid, FALSE);
atomic_dec(&open_file->wrtPending);
- cFYI(1,("SetFSize for attrs rc = %d", rc));
- if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
- int bytes_written;
+ cFYI(1, ("SetFSize for attrs rc = %d", rc));
+ if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
+ unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL,
1 /* 45 seconds */);
- cFYI(1,("Wrt seteof rc %d", rc));
+ cFYI(1, ("Wrt seteof rc %d", rc));
}
- } else
+ } else
rc = -EINVAL;
if (rc != 0) {
it by handle */
rc = CIFSSMBSetEOF(xid, pTcon, full_path,
attrs->ia_size, FALSE,
- cifs_sb->local_nls,
+ cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
- if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
+ if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid;
int oplock = FALSE;
NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc==0) {
- int bytes_written;
+ if (rc == 0) {
+ unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
netfid, 0,
attrs->ia_size,
&bytes_written, NULL,
NULL, 1 /* 45 sec */);
- cFYI(1,("wrt seteof rc %d",rc));
+ cFYI(1, ("wrt seteof rc %d", rc));
CIFSSMBClose(xid, pTcon, netfid);
}
rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
cifs_truncate_page(direntry->d_inode->i_mapping,
direntry->d_inode->i_size);
- } else
+ } else
goto cifs_setattr_exit;
}
if (attrs->ia_valid & ATTR_UID) {
}
time_buf.Attributes = 0;
+
+ /* skip mode change if it's just for clearing setuid/setgid */
+ if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+ attrs->ia_valid &= ~ATTR_MODE;
+
if (attrs->ia_valid & ATTR_MODE) {
cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
mode = attrs->ia_mode;
}
- if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ if ((pTcon->unix_ext)
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
0 /* dev_t */, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
else if (attrs->ia_valid & ATTR_MODE) {
rc = 0;
time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
(~ATTR_READONLY));
/* Windows ignores set to zero */
- if(time_buf.Attributes == 0)
+ if (time_buf.Attributes == 0)
time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
}
/* BB to be implemented -
stamps are changed explicitly (i.e. by utime()
since we would then have a mix of client and
server times */
-
+
if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
set_time = TRUE;
/* Although Samba throws this field away
NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc==0) {
+ if (rc == 0) {
rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
netfid);
CIFSSMBClose(xid, pTcon, netfid);
granularity */
/* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
- &time_buf, cifs_sb->local_nls); */
+ &time_buf, cifs_sb->local_nls); */
}
}
/* Even if error on time set, no sense failing the call if
and this check ensures that we are not being called from
sys_utimes in which case we ought to fail the call back to
the user when the server rejects the call */
- if((rc) && (attrs->ia_valid &
+ if ((rc) && (attrs->ia_valid &
(ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
rc = 0;
}