cifs: refactor new_inode() calls and inode initialization
Move new inode creation into a separate routine and refactor the callers to take advantage of it. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
committed by
Steve French
parent
e4cce94c9c
commit
132ac7b77c
@@ -92,6 +92,8 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
|
|||||||
extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
|
extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
|
||||||
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
|
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
|
||||||
|
|
||||||
|
extern struct inode *cifs_new_inode(struct super_block *sb,
|
||||||
|
unsigned long *inum);
|
||||||
extern int cifs_get_inode_info(struct inode **pinode,
|
extern int cifs_get_inode_info(struct inode **pinode,
|
||||||
const unsigned char *search_path,
|
const unsigned char *search_path,
|
||||||
FILE_ALL_INFO *pfile_info,
|
FILE_ALL_INFO *pfile_info,
|
||||||
|
@@ -199,6 +199,49 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
|
|||||||
pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
|
pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cifs_new inode - create new inode, initialize, and hash it
|
||||||
|
* @sb - pointer to superblock
|
||||||
|
* @inum - if valid pointer and serverino is enabled, replace i_ino with val
|
||||||
|
*
|
||||||
|
* Create a new inode, initialize it for CIFS and hash it. Returns the new
|
||||||
|
* inode or NULL if one couldn't be allocated.
|
||||||
|
*
|
||||||
|
* If the share isn't mounted with "serverino" or inum is a NULL pointer then
|
||||||
|
* we'll just use the inode number assigned by new_inode(). Note that this can
|
||||||
|
* mean i_ino collisions since the i_ino assigned by new_inode is not
|
||||||
|
* guaranteed to be unique.
|
||||||
|
*/
|
||||||
|
struct inode *
|
||||||
|
cifs_new_inode(struct super_block *sb, unsigned long *inum)
|
||||||
|
{
|
||||||
|
struct inode *inode;
|
||||||
|
|
||||||
|
inode = new_inode(sb);
|
||||||
|
if (inode == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we
|
||||||
|
* stop passing inum as ptr. Are there sanity checks we can use to
|
||||||
|
* ensure that the server is really filling in that field? Also,
|
||||||
|
* if serverino is disabled, perhaps we should be using iunique()?
|
||||||
|
*/
|
||||||
|
if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
|
||||||
|
inode->i_ino = *inum;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* must set this here instead of cifs_alloc_inode since VFS will
|
||||||
|
* clobber i_flags
|
||||||
|
*/
|
||||||
|
if (sb->s_flags & MS_NOATIME)
|
||||||
|
inode->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||||
|
|
||||||
|
insert_inode_hash(inode);
|
||||||
|
|
||||||
|
return inode;
|
||||||
|
}
|
||||||
|
|
||||||
int cifs_get_inode_info_unix(struct inode **pinode,
|
int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
const unsigned char *full_path, struct super_block *sb, int xid)
|
const unsigned char *full_path, struct super_block *sb, int xid)
|
||||||
{
|
{
|
||||||
@@ -233,22 +276,12 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||||||
|
|
||||||
/* get new inode */
|
/* get new inode */
|
||||||
if (*pinode == NULL) {
|
if (*pinode == NULL) {
|
||||||
*pinode = new_inode(sb);
|
*pinode = cifs_new_inode(sb, (unsigned long *)
|
||||||
|
&find_data.UniqueId);
|
||||||
if (*pinode == NULL) {
|
if (*pinode == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto cgiiu_exit;
|
goto cgiiu_exit;
|
||||||
}
|
}
|
||||||
/* Is an i_ino of zero legal? */
|
|
||||||
/* note ino incremented to unique num in new_inode */
|
|
||||||
/* Are there sanity checks we can use to ensure that
|
|
||||||
the server is really filling in that field? */
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
|
||||||
(*pinode)->i_ino = (unsigned long)find_data.UniqueId;
|
|
||||||
|
|
||||||
if (sb->s_flags & MS_NOATIME)
|
|
||||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
|
||||||
|
|
||||||
insert_inode_hash(*pinode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = *pinode;
|
inode = *pinode;
|
||||||
@@ -465,11 +498,8 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||||||
|
|
||||||
/* get new inode */
|
/* get new inode */
|
||||||
if (*pinode == NULL) {
|
if (*pinode == NULL) {
|
||||||
*pinode = new_inode(sb);
|
__u64 inode_num;
|
||||||
if (*pinode == NULL) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto cgii_exit;
|
|
||||||
}
|
|
||||||
/* Is an i_ino of zero legal? Can we use that to check
|
/* Is an i_ino of zero legal? Can we use that to check
|
||||||
if the server supports returning inode numbers? Are
|
if the server supports returning inode numbers? Are
|
||||||
there other sanity checks we can use to ensure that
|
there other sanity checks we can use to ensure that
|
||||||
@@ -486,7 +516,6 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||||
int rc1 = 0;
|
int rc1 = 0;
|
||||||
__u64 inode_num;
|
|
||||||
|
|
||||||
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
|
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
|
||||||
full_path, &inode_num,
|
full_path, &inode_num,
|
||||||
@@ -496,12 +525,17 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||||||
if (rc1) {
|
if (rc1) {
|
||||||
cFYI(1, ("GetSrvInodeNum rc %d", rc1));
|
cFYI(1, ("GetSrvInodeNum rc %d", rc1));
|
||||||
/* BB EOPNOSUPP disable SERVER_INUM? */
|
/* BB EOPNOSUPP disable SERVER_INUM? */
|
||||||
} else /* do we need cast or hash to ino? */
|
}
|
||||||
(*pinode)->i_ino = inode_num;
|
*pinode = cifs_new_inode(sb, (unsigned long *)
|
||||||
} /* else ino incremented to unique num in new_inode*/
|
&inode_num);
|
||||||
if (sb->s_flags & MS_NOATIME)
|
} else {
|
||||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
*pinode = cifs_new_inode(sb, NULL);
|
||||||
insert_inode_hash(*pinode);
|
}
|
||||||
|
|
||||||
|
if (*pinode == NULL) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto cgii_exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inode = *pinode;
|
inode = *pinode;
|
||||||
cifsInfo = CIFS_I(inode);
|
cifsInfo = CIFS_I(inode);
|
||||||
@@ -1114,24 +1148,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
|||||||
else
|
else
|
||||||
direntry->d_op = &cifs_dentry_ops;
|
direntry->d_op = &cifs_dentry_ops;
|
||||||
|
|
||||||
newinode = new_inode(inode->i_sb);
|
newinode = cifs_new_inode(inode->i_sb, (unsigned long *)
|
||||||
|
&pInfo->UniqueId);
|
||||||
if (newinode == NULL) {
|
if (newinode == NULL) {
|
||||||
kfree(pInfo);
|
kfree(pInfo);
|
||||||
goto mkdir_get_info;
|
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? */
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
|
||||||
newinode->i_ino =
|
|
||||||
(unsigned long)pInfo->UniqueId;
|
|
||||||
} /* note ino incremented to unique num in new_inode */
|
|
||||||
if (inode->i_sb->s_flags & MS_NOATIME)
|
|
||||||
newinode->i_flags |= S_NOATIME | S_NOCMTIME;
|
|
||||||
newinode->i_nlink = 2;
|
newinode->i_nlink = 2;
|
||||||
|
|
||||||
insert_inode_hash(newinode);
|
|
||||||
d_instantiate(direntry, newinode);
|
d_instantiate(direntry, newinode);
|
||||||
|
|
||||||
/* we already checked in POSIXCreate whether
|
/* we already checked in POSIXCreate whether
|
||||||
|
@@ -56,35 +56,34 @@ static inline void dump_cifs_file_struct(struct file *file, char *label)
|
|||||||
}
|
}
|
||||||
#endif /* DEBUG2 */
|
#endif /* DEBUG2 */
|
||||||
|
|
||||||
/* Returns one if new inode created (which therefore needs to be hashed) */
|
/* Returns 1 if new inode created, 2 if both dentry and inode were */
|
||||||
/* Might check in the future if inode number changed so we can rehash inode */
|
/* Might check in the future if inode number changed so we can rehash inode */
|
||||||
static int construct_dentry(struct qstr *qstring, struct file *file,
|
static int
|
||||||
struct inode **ptmp_inode, struct dentry **pnew_dentry)
|
construct_dentry(struct qstr *qstring, struct file *file,
|
||||||
|
struct inode **ptmp_inode, struct dentry **pnew_dentry,
|
||||||
|
unsigned long *inum)
|
||||||
{
|
{
|
||||||
struct dentry *tmp_dentry;
|
struct dentry *tmp_dentry = NULL;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct super_block *sb = file->f_path.dentry->d_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
cFYI(1, ("For %s", qstring->name));
|
cFYI(1, ("For %s", qstring->name));
|
||||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
|
||||||
pTcon = cifs_sb->tcon;
|
|
||||||
|
|
||||||
qstring->hash = full_name_hash(qstring->name, qstring->len);
|
qstring->hash = full_name_hash(qstring->name, qstring->len);
|
||||||
tmp_dentry = d_lookup(file->f_path.dentry, qstring);
|
tmp_dentry = d_lookup(file->f_path.dentry, qstring);
|
||||||
if (tmp_dentry) {
|
if (tmp_dentry) {
|
||||||
|
/* BB: overwrite old name? i.e. tmp_dentry->d_name and
|
||||||
|
* tmp_dentry->d_name.len??
|
||||||
|
*/
|
||||||
cFYI(0, ("existing dentry with inode 0x%p",
|
cFYI(0, ("existing dentry with inode 0x%p",
|
||||||
tmp_dentry->d_inode));
|
tmp_dentry->d_inode));
|
||||||
*ptmp_inode = tmp_dentry->d_inode;
|
*ptmp_inode = tmp_dentry->d_inode;
|
||||||
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
|
|
||||||
if (*ptmp_inode == NULL) {
|
if (*ptmp_inode == NULL) {
|
||||||
*ptmp_inode = new_inode(file->f_path.dentry->d_sb);
|
*ptmp_inode = cifs_new_inode(sb, inum);
|
||||||
if (*ptmp_inode == NULL)
|
if (*ptmp_inode == NULL)
|
||||||
return rc;
|
return rc;
|
||||||
rc = 1;
|
rc = 1;
|
||||||
}
|
}
|
||||||
if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
|
|
||||||
(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
|
||||||
} else {
|
} else {
|
||||||
tmp_dentry = d_alloc(file->f_path.dentry, qstring);
|
tmp_dentry = d_alloc(file->f_path.dentry, qstring);
|
||||||
if (tmp_dentry == NULL) {
|
if (tmp_dentry == NULL) {
|
||||||
@@ -93,15 +92,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ptmp_inode = new_inode(file->f_path.dentry->d_sb);
|
if (CIFS_SB(sb)->tcon->nocase)
|
||||||
if (pTcon->nocase)
|
|
||||||
tmp_dentry->d_op = &cifs_ci_dentry_ops;
|
tmp_dentry->d_op = &cifs_ci_dentry_ops;
|
||||||
else
|
else
|
||||||
tmp_dentry->d_op = &cifs_dentry_ops;
|
tmp_dentry->d_op = &cifs_dentry_ops;
|
||||||
|
|
||||||
|
*ptmp_inode = cifs_new_inode(sb, inum);
|
||||||
if (*ptmp_inode == NULL)
|
if (*ptmp_inode == NULL)
|
||||||
return rc;
|
return rc;
|
||||||
if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
|
|
||||||
(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
|
||||||
rc = 2;
|
rc = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -842,8 +840,6 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
|
|||||||
len = strnlen(filename, PATH_MAX);
|
len = strnlen(filename, PATH_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB */
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
|
||||||
*pinum = pFindData->UniqueId;
|
*pinum = pFindData->UniqueId;
|
||||||
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||||
FILE_DIRECTORY_INFO *pFindData =
|
FILE_DIRECTORY_INFO *pFindData =
|
||||||
@@ -940,20 +936,18 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry);
|
/* only these two infolevels return valid inode numbers */
|
||||||
|
if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX ||
|
||||||
|
pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
|
||||||
|
rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
|
||||||
|
&inum);
|
||||||
|
else
|
||||||
|
rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if ((tmp_inode == NULL) || (tmp_dentry == NULL))
|
if ((tmp_inode == NULL) || (tmp_dentry == NULL))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
/* inode created, we need to hash it with right inode number */
|
|
||||||
if (inum != 0) {
|
|
||||||
/* BB fixme - hash the 2 32 quantities bits together if
|
|
||||||
* necessary BB */
|
|
||||||
tmp_inode->i_ino = inum;
|
|
||||||
}
|
|
||||||
insert_inode_hash(tmp_inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we pass in rc below, indicating whether it is a new inode,
|
/* we pass in rc below, indicating whether it is a new inode,
|
||||||
so we can figure out whether to invalidate the inode cached
|
so we can figure out whether to invalidate the inode cached
|
||||||
data if the file has changed */
|
data if the file has changed */
|
||||||
|
Reference in New Issue
Block a user