Skip to content

Commit

Permalink
cifs: add new cifs_iget function and convert unix codepath to use it
Browse files Browse the repository at this point in the history
cifs: add new cifs_iget function and convert unix codepath to use it

In order to unify some codepaths, introduce a common cifs_fattr struct
for storing inode attributes. The different codepaths (unix, legacy,
normal, etc...) can fill out this struct with inode info. It can then be
passed as an arg to a common set of routines to get and update inodes.

Add a new cifs_iget function that uses iget5_locked to identify inodes.
This will compare inodes based on the uniqueid value in a cifs_fattr
struct.

Rather than filling out an already-created inode, have
cifs_get_inode_info_unix instead fill out cifs_fattr and hand that off
to cifs_iget. cifs_iget can then properly look for hardlinked inodes.

On the readdir side, add a new cifs_readdir_lookup function that spawns
populated dentries. Redefine FILE_UNIX_INFO so that it's basically a
FILE_UNIX_BASIC_INFO that has a few fields wrapped around it. This
allows us to more easily use the same function for filling out the fattr
as the non-readdir codepath.

With this, we should then have proper hardlink detection and can
eventually get rid of some nasty CIFS-specific hacks for handing them.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Steve French <sfrench@us.ibm.com>
  • Loading branch information
Jeff Layton authored and Steve French committed Jul 1, 2009
1 parent d960eea commit cc0bad7
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 377 deletions.
13 changes: 13 additions & 0 deletions fs/cifs/cifsfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@

#define ROOT_I 2

/*
* ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
* so that it will fit.
*/
static inline ino_t
cifs_uniqueid_to_ino_t(u64 fileid)
{
ino_t ino = (ino_t) fileid;
if (sizeof(ino_t) < sizeof(u64))
ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8;
return ino;
}

extern struct file_system_type cifs_fs_type;
extern const struct address_space_operations cifs_addr_ops;
extern const struct address_space_operations cifs_addr_ops_smallbuf;
Expand Down
25 changes: 25 additions & 0 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ struct cifsInodeInfo {
bool oplockPending:1;
bool delete_pending:1; /* DELETE_ON_CLOSE is set */
u64 server_eof; /* current file size on server */
u64 uniqueid; /* server inode number */
struct inode vfs_inode;
};

Expand Down Expand Up @@ -472,6 +473,30 @@ struct dfs_info3_param {
char *node_name;
};

/*
* common struct for holding inode info when searching for or updating an
* inode with new info
*/

#define CIFS_FATTR_DFS_REFERRAL 0x1

struct cifs_fattr {
u32 cf_flags;
u32 cf_cifsattrs;
u64 cf_uniqueid;
u64 cf_eof;
u64 cf_bytes;
uid_t cf_uid;
gid_t cf_gid;
umode_t cf_mode;
dev_t cf_rdev;
unsigned int cf_nlink;
unsigned int cf_dtype;
struct timespec cf_atime;
struct timespec cf_mtime;
struct timespec cf_ctime;
};

static inline void free_dfs_info_param(struct dfs_info3_param *param)
{
if (param) {
Expand Down
14 changes: 1 addition & 13 deletions fs/cifs/cifspdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -2328,19 +2328,7 @@ struct file_attrib_tag {
typedef struct {
__le32 NextEntryOffset;
__u32 ResumeKey; /* as with FileIndex - no need to convert */
__le64 EndOfFile;
__le64 NumOfBytes;
__le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */
__le64 LastAccessTime;
__le64 LastModificationTime;
__le64 Uid;
__le64 Gid;
__le32 Type;
__le64 DevMajor;
__le64 DevMinor;
__le64 UniqueId;
__le64 Permissions;
__le64 Nlinks;
FILE_UNIX_BASIC_INFO basic;
char FileName[1];
} __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */

Expand Down
9 changes: 7 additions & 2 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,14 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
extern int cifs_posix_open(char *full_path, struct inode **pinode,
struct super_block *sb, int mode, int oflags,
int *poplock, __u16 *pnetfid, int xid);
extern void posix_fill_in_inode(struct inode *tmp_inode,
FILE_UNIX_BASIC_INFO *pData, int isNewInode);
extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
FILE_UNIX_BASIC_INFO *info,
struct cifs_sb_info *cifs_sb);
extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum);
extern struct inode *cifs_iget(struct super_block *sb,
struct cifs_fattr *fattr);

extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path,
FILE_ALL_INFO *pfile_info,
Expand Down
22 changes: 11 additions & 11 deletions fs/cifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
FILE_UNIX_BASIC_INFO *presp_data;
__u32 posix_flags = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_fattr fattr;

cFYI(1, ("posix open %s", full_path));

Expand Down Expand Up @@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
if (presp_data->Type == cpu_to_le32(-1))
goto posix_open_ret; /* open ok, caller does qpathinfo */

/* get new inode and set it up */
if (!pinode)
goto posix_open_ret; /* caller does not need info */

cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);

/* get new inode and set it up */
if (*pinode == NULL) {
__u64 unique_id = le64_to_cpu(presp_data->UniqueId);
*pinode = cifs_new_inode(sb, &unique_id);
*pinode = cifs_iget(sb, &fattr);
if (!*pinode) {
rc = -ENOMEM;
goto posix_open_ret;
}
} else {
cifs_fattr_to_inode(*pinode, &fattr);
}
/* else an inode was passed in. Update its info, don't create one */

/* We do not need to close the file if new_inode fails since
the caller will retry qpathinfo as long as inode is null */
if (*pinode == NULL)
goto posix_open_ret;

posix_fill_in_inode(*pinode, presp_data, 1);

cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);

Expand Down
Loading

0 comments on commit cc0bad7

Please sign in to comment.