Merge branch 'for-next'
This commit is contained in:
229
fs/cifs/inode.c
229
fs/cifs/inode.c
@@ -52,7 +52,7 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
|
||||
|
||||
|
||||
/* check if server can support readpages */
|
||||
if (cifs_sb->tcon->ses->server->maxBuf <
|
||||
if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
|
||||
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
@@ -288,8 +288,8 @@ int cifs_get_file_info_unix(struct file *filp)
|
||||
struct cifs_fattr fattr;
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsTconInfo *tcon = cifs_sb->tcon;
|
||||
struct cifsFileInfo *cfile = filp->private_data;
|
||||
struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink);
|
||||
|
||||
xid = GetXid();
|
||||
rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
|
||||
@@ -313,15 +313,21 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
FILE_UNIX_BASIC_INFO find_data;
|
||||
struct cifs_fattr fattr;
|
||||
struct cifsTconInfo *tcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
|
||||
tcon = cifs_sb->tcon;
|
||||
cFYI(1, "Getting info on %s", full_path);
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
/* could have done a find first instead but this returns more info */
|
||||
rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cifs_put_tlink(tlink);
|
||||
|
||||
if (!rc) {
|
||||
cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
|
||||
@@ -332,6 +338,13 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* check for Minshall+French symlinks */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
|
||||
if (tmprc)
|
||||
cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
|
||||
}
|
||||
|
||||
if (*pinode == NULL) {
|
||||
/* get new inode */
|
||||
cifs_fill_uniqueid(sb, &fattr);
|
||||
@@ -353,7 +366,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
int rc;
|
||||
int oplock = 0;
|
||||
__u16 netfid;
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *tcon;
|
||||
char buf[24];
|
||||
unsigned int bytes_read;
|
||||
char *pbuf;
|
||||
@@ -372,7 +386,12 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
return -EINVAL; /* EOPNOTSUPP? */
|
||||
}
|
||||
|
||||
rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
|
||||
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
@@ -380,7 +399,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
if (rc == 0) {
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
/* Read header */
|
||||
rc = CIFSSMBRead(xid, pTcon, netfid,
|
||||
rc = CIFSSMBRead(xid, tcon, netfid,
|
||||
24 /* length */, 0 /* offset */,
|
||||
&bytes_read, &pbuf, &buf_type);
|
||||
if ((rc == 0) && (bytes_read >= 8)) {
|
||||
@@ -422,8 +441,9 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
fattr->cf_dtype = DT_REG;
|
||||
rc = -EOPNOTSUPP; /* or some unknown SFU type */
|
||||
}
|
||||
CIFSSMBClose(xid, pTcon, netfid);
|
||||
CIFSSMBClose(xid, tcon, netfid);
|
||||
}
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -441,11 +461,19 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
ssize_t rc;
|
||||
char ea_value[4];
|
||||
__u32 mode;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *tcon;
|
||||
|
||||
rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
|
||||
ea_value, 4 /* size of buf */, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cifs_put_tlink(tlink);
|
||||
if (rc < 0)
|
||||
return (int)rc;
|
||||
else if (rc > 3) {
|
||||
@@ -468,6 +496,8 @@ static void
|
||||
cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
|
||||
struct cifs_sb_info *cifs_sb, bool adjust_tz)
|
||||
{
|
||||
struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
memset(fattr, 0, sizeof(*fattr));
|
||||
fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
|
||||
if (info->DeletePending)
|
||||
@@ -482,8 +512,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
|
||||
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
|
||||
|
||||
if (adjust_tz) {
|
||||
fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
|
||||
fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
|
||||
fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
|
||||
fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
|
||||
}
|
||||
|
||||
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
|
||||
@@ -515,8 +545,8 @@ int cifs_get_file_info(struct file *filp)
|
||||
struct cifs_fattr fattr;
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsTconInfo *tcon = cifs_sb->tcon;
|
||||
struct cifsFileInfo *cfile = filp->private_data;
|
||||
struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink);
|
||||
|
||||
xid = GetXid();
|
||||
rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
|
||||
@@ -554,26 +584,33 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
{
|
||||
int rc = 0, tmprc;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
char *buf = NULL;
|
||||
bool adjustTZ = false;
|
||||
struct cifs_fattr fattr;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
cFYI(1, "Getting info on %s", full_path);
|
||||
|
||||
if ((pfindData == NULL) && (*pinode != NULL)) {
|
||||
if (CIFS_I(*pinode)->clientCanCacheRead) {
|
||||
cFYI(1, "No need to revalidate cached inode sizes");
|
||||
return rc;
|
||||
goto cgii_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* if file info not passed in then get it from server */
|
||||
if (pfindData == NULL) {
|
||||
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
if (buf == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto cgii_exit;
|
||||
}
|
||||
pfindData = (FILE_ALL_INFO *)buf;
|
||||
|
||||
/* could do find first instead but this returns more info */
|
||||
@@ -661,6 +698,13 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
|
||||
cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
|
||||
|
||||
/* check for Minshall+French symlinks */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
|
||||
if (tmprc)
|
||||
cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
|
||||
}
|
||||
|
||||
if (!*pinode) {
|
||||
*pinode = cifs_iget(sb, &fattr);
|
||||
if (!*pinode)
|
||||
@@ -671,6 +715,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
|
||||
cgii_exit:
|
||||
kfree(buf);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -683,6 +728,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
|
||||
int pplen = cifs_sb->prepathlen;
|
||||
int dfsplen;
|
||||
char *full_path = NULL;
|
||||
struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
/* if no prefix path, simply set path to the root of share to "" */
|
||||
if (pplen == 0) {
|
||||
@@ -692,8 +738,8 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
|
||||
return full_path;
|
||||
}
|
||||
|
||||
if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
|
||||
dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
|
||||
if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
|
||||
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
|
||||
else
|
||||
dfsplen = 0;
|
||||
|
||||
@@ -702,7 +748,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
|
||||
return full_path;
|
||||
|
||||
if (dfsplen) {
|
||||
strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
|
||||
strncpy(full_path, tcon->treeName, dfsplen);
|
||||
/* switch slash direction in prepath depending on whether
|
||||
* windows or posix style path names
|
||||
*/
|
||||
@@ -818,18 +864,18 @@ retry_iget5_locked:
|
||||
struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
|
||||
{
|
||||
int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct inode *inode = NULL;
|
||||
long rc;
|
||||
char *full_path;
|
||||
struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
full_path = cifs_build_path_to_root(cifs_sb);
|
||||
if (full_path == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
xid = GetXid();
|
||||
if (cifs_sb->tcon->unix_ext)
|
||||
if (tcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
|
||||
@@ -840,10 +886,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
|
||||
|
||||
#ifdef CONFIG_CIFS_FSCACHE
|
||||
/* populate tcon->resource_id */
|
||||
cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid;
|
||||
tcon->resource_id = CIFS_I(inode)->uniqueid;
|
||||
#endif
|
||||
|
||||
if (rc && cifs_sb->tcon->ipc) {
|
||||
if (rc && tcon->ipc) {
|
||||
cFYI(1, "ipc connection - fake read inode");
|
||||
inode->i_mode |= S_IFDIR;
|
||||
inode->i_nlink = 2;
|
||||
@@ -879,7 +925,8 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
|
||||
struct cifsFileInfo *open_file;
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
struct tcon_link *tlink = NULL;
|
||||
struct cifsTconInfo *pTcon;
|
||||
FILE_BASIC_INFO info_buf;
|
||||
|
||||
if (attrs == NULL)
|
||||
@@ -918,13 +965,22 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
|
||||
/*
|
||||
* If the file is already open for write, just use that fileid
|
||||
*/
|
||||
open_file = find_writable_file(cifsInode);
|
||||
open_file = find_writable_file(cifsInode, true);
|
||||
if (open_file) {
|
||||
netfid = open_file->netfid;
|
||||
netpid = open_file->pid;
|
||||
pTcon = tlink_tcon(open_file->tlink);
|
||||
goto set_via_filehandle;
|
||||
}
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink)) {
|
||||
rc = PTR_ERR(tlink);
|
||||
tlink = NULL;
|
||||
goto out;
|
||||
}
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
/*
|
||||
* NT4 apparently returns success on this call, but it doesn't
|
||||
* really work.
|
||||
@@ -968,6 +1024,8 @@ set_via_filehandle:
|
||||
else
|
||||
cifsFileInfo_put(open_file);
|
||||
out:
|
||||
if (tlink != NULL)
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -985,10 +1043,16 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsTconInfo *tcon = cifs_sb->tcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *tcon;
|
||||
__u32 dosattr, origattr;
|
||||
FILE_BASIC_INFO *info_buf = NULL;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
|
||||
DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
|
||||
&netfid, &oplock, NULL, cifs_sb->local_nls,
|
||||
@@ -1057,6 +1121,7 @@ out_close:
|
||||
CIFSSMBClose(xid, tcon, netfid);
|
||||
out:
|
||||
kfree(info_buf);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
|
||||
/*
|
||||
@@ -1096,12 +1161,18 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
struct cifsInodeInfo *cifs_inode;
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifsTconInfo *tcon = cifs_sb->tcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *tcon;
|
||||
struct iattr *attrs = NULL;
|
||||
__u32 dosattr = 0, origattr = 0;
|
||||
|
||||
cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
/* Unlink can be called from rename so we can not take the
|
||||
@@ -1109,8 +1180,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
full_path = build_path_from_dentry(dentry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
goto unlink_out;
|
||||
}
|
||||
|
||||
if ((tcon->ses->capabilities & CAP_UNIX) &&
|
||||
@@ -1176,10 +1246,11 @@ out_reval:
|
||||
dir->i_ctime = dir->i_mtime = current_fs_time(sb);
|
||||
cifs_inode = CIFS_I(dir);
|
||||
CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
|
||||
|
||||
unlink_out:
|
||||
kfree(full_path);
|
||||
kfree(attrs);
|
||||
FreeXid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1188,6 +1259,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
int rc = 0, tmprc;
|
||||
int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *pTcon;
|
||||
char *full_path = NULL;
|
||||
struct inode *newinode = NULL;
|
||||
@@ -1195,16 +1267,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
|
||||
cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode);
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
if ((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||
@@ -1362,6 +1436,7 @@ mkdir_get_info:
|
||||
mkdir_out:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1370,6 +1445,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
int rc = 0;
|
||||
int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *pTcon;
|
||||
char *full_path = NULL;
|
||||
struct cifsInodeInfo *cifsInode;
|
||||
@@ -1378,18 +1454,23 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
goto rmdir_exit;
|
||||
}
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink)) {
|
||||
rc = PTR_ERR(tlink);
|
||||
goto rmdir_exit;
|
||||
}
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cifs_put_tlink(tlink);
|
||||
|
||||
if (!rc) {
|
||||
drop_nlink(inode);
|
||||
@@ -1410,6 +1491,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
|
||||
current_fs_time(inode->i_sb);
|
||||
|
||||
rmdir_exit:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
@@ -1420,10 +1502,16 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
|
||||
struct dentry *to_dentry, const char *toPath)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *pTcon;
|
||||
__u16 srcfid;
|
||||
int oplock, rc;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
/* try path-based rename first */
|
||||
rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
@@ -1435,11 +1523,11 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
|
||||
* rename by filehandle to various Windows servers.
|
||||
*/
|
||||
if (rc == 0 || rc != -ETXTBSY)
|
||||
return rc;
|
||||
goto do_rename_exit;
|
||||
|
||||
/* open-file renames don't work across directories */
|
||||
if (to_dentry->d_parent != from_dentry->d_parent)
|
||||
return rc;
|
||||
goto do_rename_exit;
|
||||
|
||||
/* open the file to be renamed -- we need DELETE perms */
|
||||
rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
|
||||
@@ -1455,7 +1543,8 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
|
||||
|
||||
CIFSSMBClose(xid, pTcon, srcfid);
|
||||
}
|
||||
|
||||
do_rename_exit:
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1465,13 +1554,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
||||
char *fromName = NULL;
|
||||
char *toName = NULL;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *tcon;
|
||||
FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
|
||||
FILE_UNIX_BASIC_INFO *info_buf_target;
|
||||
int xid, rc, tmprc;
|
||||
|
||||
cifs_sb = CIFS_SB(source_dir->i_sb);
|
||||
tcon = cifs_sb->tcon;
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
@@ -1547,6 +1640,7 @@ cifs_rename_exit:
|
||||
kfree(fromName);
|
||||
kfree(toName);
|
||||
FreeXid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1599,11 +1693,12 @@ int cifs_revalidate_file(struct file *filp)
|
||||
{
|
||||
int rc = 0;
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
|
||||
|
||||
if (!cifs_inode_needs_reval(inode))
|
||||
goto check_inval;
|
||||
|
||||
if (CIFS_SB(inode->i_sb)->tcon->unix_ext)
|
||||
if (tlink_tcon(cfile->tlink)->unix_ext)
|
||||
rc = cifs_get_file_info_unix(filp);
|
||||
else
|
||||
rc = cifs_get_file_info(filp);
|
||||
@@ -1644,7 +1739,7 @@ int cifs_revalidate_dentry(struct dentry *dentry)
|
||||
"jiffies %ld", full_path, inode, inode->i_count.counter,
|
||||
dentry, dentry->d_time, jiffies);
|
||||
|
||||
if (CIFS_SB(sb)->tcon->unix_ext)
|
||||
if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
|
||||
@@ -1662,11 +1757,21 @@ check_inval:
|
||||
int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
|
||||
struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
int err = cifs_revalidate_dentry(dentry);
|
||||
|
||||
if (!err) {
|
||||
generic_fillattr(dentry->d_inode, stat);
|
||||
stat->blksize = CIFS_MAX_MSGSIZE;
|
||||
stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
|
||||
!tcon->unix_ext) {
|
||||
if (!cifs_sb->mnt_uid)
|
||||
stat->uid = current_fsuid();
|
||||
if (!cifs_sb->mnt_uid)
|
||||
stat->gid = current_fsgid();
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -1708,7 +1813,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||
struct cifsFileInfo *open_file;
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
struct tcon_link *tlink = NULL;
|
||||
struct cifsTconInfo *pTcon = NULL;
|
||||
|
||||
/*
|
||||
* To avoid spurious oplock breaks from server, in the case of
|
||||
@@ -1719,10 +1825,11 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||
* writebehind data than the SMB timeout for the SetPathInfo
|
||||
* request would allow
|
||||
*/
|
||||
open_file = find_writable_file(cifsInode);
|
||||
open_file = find_writable_file(cifsInode, true);
|
||||
if (open_file) {
|
||||
__u16 nfid = open_file->netfid;
|
||||
__u32 npid = open_file->pid;
|
||||
pTcon = tlink_tcon(open_file->tlink);
|
||||
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
|
||||
npid, false);
|
||||
cifsFileInfo_put(open_file);
|
||||
@@ -1737,6 +1844,13 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||
rc = -EINVAL;
|
||||
|
||||
if (rc != 0) {
|
||||
if (pTcon == NULL) {
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
}
|
||||
|
||||
/* Set file size by pathname rather than by handle
|
||||
either because no valid, writeable file handle for
|
||||
it was found or because there was an error setting
|
||||
@@ -1766,6 +1880,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||
CIFSSMBClose(xid, pTcon, netfid);
|
||||
}
|
||||
}
|
||||
if (tlink)
|
||||
cifs_put_tlink(tlink);
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
@@ -1786,7 +1902,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
struct inode *inode = direntry->d_inode;
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct cifs_unix_set_info_args *args = NULL;
|
||||
struct cifsFileInfo *open_file;
|
||||
|
||||
@@ -1873,17 +1990,25 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
args->ctime = NO_CHANGE_64;
|
||||
|
||||
args->device = 0;
|
||||
open_file = find_writable_file(cifsInode);
|
||||
open_file = find_writable_file(cifsInode, true);
|
||||
if (open_file) {
|
||||
u16 nfid = open_file->netfid;
|
||||
u32 npid = open_file->pid;
|
||||
pTcon = tlink_tcon(open_file->tlink);
|
||||
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
|
||||
cifsFileInfo_put(open_file);
|
||||
} else {
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink)) {
|
||||
rc = PTR_ERR(tlink);
|
||||
goto out;
|
||||
}
|
||||
pTcon = tlink_tcon(tlink);
|
||||
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cifs_put_tlink(tlink);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
@@ -2064,7 +2189,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
{
|
||||
struct inode *inode = direntry->d_inode;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
struct cifsTconInfo *pTcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
if (pTcon->unix_ext)
|
||||
return cifs_setattr_unix(direntry, attrs);
|
||||
|
Reference in New Issue
Block a user