All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] cifs: implement proper hardlink detection
@ 2009-05-11 20:24 Jeff Layton
  2009-05-11 20:24 ` [PATCH 01/13] cifs: have cifs_NTtimeToUnix take a little-endian arg Jeff Layton
                   ` (12 more replies)
  0 siblings, 13 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

This is a second pass at a patchset to implement proper hardlink
handling in CIFS. The first set was posted a little more than a month
ago and only implemented this for mounts with posix extensions. This
patchset should also implement it for non-posix mounts, as long as the
server is capable of reporting uniqueid's.

The idea here is to add a new cifs_fattr struct that acts as a container
for file attributes returned by the server. Each "dialect" has a
translation routine that converts the info returned by the server to
this container.

This approach allows us to use iget5_locked get references to inodes,
which allows us to identify hardlinks at inode instantiation time. It
also results in around a 250 line reduction in code. This is mostly due
to the fact that the patchset eliminates a lot of cut-and-paste code
duplication and some hardlink handling hackery that should no longer be
needed.

The set should be bisectable if committed in order, but I've not done
any real testing on anything but the complete set. I've also only tested
it with the most commonly used options (posix extensions and nounix).
The less commonly traveled codepaths also need to be tested (cifsacl,
sfu, etc).

I see this as 2.6.31 material.

Comments and suggestions appreciated.

Jeff Layton (13):
  cifs: have cifs_NTtimeToUnix take a little-endian arg
  cifs: make cnvrtDosUnixTm take a little-endian args and an offset
  cifs: allow get_cifs_acl to be called without an inode
  cifs: rename cifs_iget to cifs_root_iget
  cifs: add new cifs_fattr struct for holding cifs inode attributes in
    common way
  cifs: add new cifs_iget function and convert unix codepath to use it
  cifs: convert posix readdir codepath to use cifs_iget
  cifs: convert cifs_get_inode_info to use cifs_iget
  cifs: convert non-posix readdir codepath to use cifs_iget
  cifs: remove cifs_new_inode
  cifs: make serverino the default when mounting
  cifs: remove cifsInodeInfo->inUse counter
  cifs: remove "hardlink detection" from cifs_rename

 fs/cifs/cifsacl.c   |   50 ++--
 fs/cifs/cifsfs.c    |    3 +-
 fs/cifs/cifsfs.h    |   15 +-
 fs/cifs/cifsglob.h  |   29 ++-
 fs/cifs/cifsproto.h |   19 +-
 fs/cifs/cifssmb.c   |    4 +-
 fs/cifs/connect.c   |    2 +
 fs/cifs/dir.c       |   25 +-
 fs/cifs/file.c      |    2 +-
 fs/cifs/inode.c     |  811 ++++++++++++++++++++++-----------------------------
 fs/cifs/netmisc.c   |   24 +-
 fs/cifs/readdir.c   |  571 +++++++++++++------------------------
 12 files changed, 649 insertions(+), 906 deletions(-)


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/13] cifs: have cifs_NTtimeToUnix take a little-endian arg
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:26   ` Christoph Hellwig
  2009-05-11 20:24 ` [PATCH 02/13] cifs: make cnvrtDosUnixTm take a little-endian args and an offset Jeff Layton
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

...and just have the function call le64_to_cpu.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsproto.h |    2 +-
 fs/cifs/file.c      |    2 +-
 fs/cifs/inode.c     |   15 ++++++---------
 fs/cifs/netmisc.c   |   12 ++++++------
 fs/cifs/readdir.c   |   12 ++++++------
 5 files changed, 20 insertions(+), 23 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index fae0839..8831f64 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -90,7 +90,7 @@ extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
 						 struct cifsTconInfo *);
 extern void DeleteOplockQEntry(struct oplock_q_entry *);
 extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
-extern struct timespec cifs_NTtimeToUnix(u64 utc_nanoseconds_since_1601);
+extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
 extern u64 cifs_UnixTimeToNT(struct timespec);
 extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
 extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 38c06f8..836bfb7 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -213,7 +213,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
 	/* BB need same check in cifs_create too? */
 	/* if not oplocked, invalidate inode pages if mtime or file
 	   size changed */
-	temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
+	temp = cifs_NTtimeToUnix(buf->LastWriteTime);
 	if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
 			   (file->f_path.dentry->d_inode->i_size ==
 			    (loff_t)le64_to_cpu(buf->EndOfFile))) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 9c869a6..42d6e0f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -85,10 +85,10 @@ static void cifs_unix_info_to_inode(struct inode *inode,
 	__u64 num_of_bytes = le64_to_cpu(info->NumOfBytes);
 	__u64 end_of_file = le64_to_cpu(info->EndOfFile);
 
-	inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(info->LastAccessTime));
+	inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime);
 	inode->i_mtime =
-		cifs_NTtimeToUnix(le64_to_cpu(info->LastModificationTime));
-	inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(info->LastStatusChange));
+		cifs_NTtimeToUnix(info->LastModificationTime);
+	inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
 	inode->i_mode = le64_to_cpu(info->Permissions);
 
 	/*
@@ -554,14 +554,11 @@ int cifs_get_inode_info(struct inode **pinode,
 
 	/* Linux can not store file creation time so ignore it */
 	if (pfindData->LastAccessTime)
-		inode->i_atime = cifs_NTtimeToUnix
-			(le64_to_cpu(pfindData->LastAccessTime));
+		inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime);
 	else /* do not need to use current_fs_time - time not stored */
 		inode->i_atime = CURRENT_TIME;
-	inode->i_mtime =
-		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
-	inode->i_ctime =
-	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
+	inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime);
+	inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime);
 	cFYI(DBG2, ("Attributes came in as 0x%x", attr));
 	if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
 		inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index e2fe998..d3ba75e 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -853,12 +853,12 @@ smbCalcSize_LE(struct smb_hdr *ptr)
 
 #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
 
-    /*
-     * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
-     * into Unix UTC (based 1970-01-01, in seconds).
-     */
+/*
+ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
+ * into Unix UTC (based 1970-01-01, in seconds).
+ */
 struct timespec
-cifs_NTtimeToUnix(u64 ntutc)
+cifs_NTtimeToUnix(__le64 ntutc)
 {
 	struct timespec ts;
 	/* BB what about the timezone? BB */
@@ -866,7 +866,7 @@ cifs_NTtimeToUnix(u64 ntutc)
 	/* Subtract the NTFS time offset, then convert to 1s intervals. */
 	u64 t;
 
-	t = ntutc - NTFS_TIME_OFFSET;
+	t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
 	ts.tv_nsec = do_div(t, 10000000) * 100;
 	ts.tv_sec = t;
 	return ts;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 964e097..79c46c2 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -150,11 +150,11 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
 		allocation_size = le64_to_cpu(pfindData->AllocationSize);
 		end_of_file = le64_to_cpu(pfindData->EndOfFile);
 		tmp_inode->i_atime =
-		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+			cifs_NTtimeToUnix(pfindData->LastAccessTime);
 		tmp_inode->i_mtime =
-		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
+			cifs_NTtimeToUnix(pfindData->LastWriteTime);
 		tmp_inode->i_ctime =
-		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
+			cifs_NTtimeToUnix(pfindData->ChangeTime);
 	} else { /* legacy, OS2 and DOS style */
 /*		struct timespec ts;*/
 		FIND_FILE_STANDARD_INFO *pfindData =
@@ -331,11 +331,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
 	local_size  = tmp_inode->i_size;
 
 	tmp_inode->i_atime =
-	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+	    cifs_NTtimeToUnix(pfindData->LastAccessTime);
 	tmp_inode->i_mtime =
-	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
+	    cifs_NTtimeToUnix(pfindData->LastModificationTime);
 	tmp_inode->i_ctime =
-	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
+	    cifs_NTtimeToUnix(pfindData->LastStatusChange);
 
 	tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
 	/* since we set the inode type below we need to mask off type
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 02/13] cifs: make cnvrtDosUnixTm take a little-endian args and an offset
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
  2009-05-11 20:24 ` [PATCH 01/13] cifs: have cifs_NTtimeToUnix take a little-endian arg Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:27   ` Christoph Hellwig
  2009-05-11 20:24 ` [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode Jeff Layton
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

The callers primarily end up converting the args from le anyway. Also,
most of the callers end up needing to add an offset to the result. The
exception to these rules is cnvrtDosCifsTm, but there are no callers of
that function, so we might as well remove it.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsproto.h |    4 ++--
 fs/cifs/cifssmb.c   |    4 ++--
 fs/cifs/netmisc.c   |   12 ++++--------
 fs/cifs/readdir.c   |   32 ++++++++++----------------------
 4 files changed, 18 insertions(+), 34 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 8831f64..d542cf1 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -92,8 +92,8 @@ extern void DeleteOplockQEntry(struct oplock_q_entry *);
 extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
 extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
 extern u64 cifs_UnixTimeToNT(struct timespec);
-extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
-extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
+extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
+				      int offset);
 
 extern int cifs_posix_open(char *full_path, struct inode **pinode,
 			   struct super_block *sb, int mode, int oflags,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 75e6623..a7bc5da 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -524,8 +524,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 			int val, seconds, remain, result;
 			struct timespec ts, utc;
 			utc = CURRENT_TIME;
-			ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
-						le16_to_cpu(rsp->SrvTime.Time));
+			ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
+					    rsp->SrvTime.Time, 0);
 			cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
 				(int)ts.tv_sec, (int)utc.tv_sec,
 				(int)(utc.tv_sec - ts.tv_sec)));
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index d3ba75e..32d6baa 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -883,16 +883,12 @@ cifs_UnixTimeToNT(struct timespec t)
 static int total_days_of_prev_months[] =
 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
 
-
-__le64 cnvrtDosCifsTm(__u16 date, __u16 time)
-{
-	return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time)));
-}
-
-struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
+struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
 {
 	struct timespec ts;
 	int sec, min, days, month, year;
+	u16 date = le16_to_cpu(le_date);
+	u16 time = le16_to_cpu(le_time);
 	SMB_TIME *st = (SMB_TIME *)&time;
 	SMB_DATE *sd = (SMB_DATE *)&date;
 
@@ -933,7 +929,7 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
 		days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
 	sec += 24 * 60 * 60 * days;
 
-	ts.tv_sec = sec;
+	ts.tv_sec = sec + offset;
 
 	/* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */
 
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 79c46c2..86d0055 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -115,17 +115,6 @@ construct_dentry(struct qstr *qstring, struct file *file,
 	return rc;
 }
 
-static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
-{
-	if ((tcon) && (tcon->ses) && (tcon->ses->server)) {
-		inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
-		inode->i_mtime.tv_sec += tcon->ses->server->timeAdj;
-		inode->i_atime.tv_sec += tcon->ses->server->timeAdj;
-	}
-	return;
-}
-
-
 static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
 			  char *buf, unsigned int *pobject_type, int isNewInode)
 {
@@ -156,20 +145,19 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
 		tmp_inode->i_ctime =
 			cifs_NTtimeToUnix(pfindData->ChangeTime);
 	} else { /* legacy, OS2 and DOS style */
-/*		struct timespec ts;*/
+		int offset = cifs_sb->tcon->ses->server->timeAdj;
 		FIND_FILE_STANDARD_INFO *pfindData =
 			(FIND_FILE_STANDARD_INFO *)buf;
 
-		tmp_inode->i_mtime = cnvrtDosUnixTm(
-				le16_to_cpu(pfindData->LastWriteDate),
-				le16_to_cpu(pfindData->LastWriteTime));
-		tmp_inode->i_atime = cnvrtDosUnixTm(
-				le16_to_cpu(pfindData->LastAccessDate),
-				le16_to_cpu(pfindData->LastAccessTime));
-		tmp_inode->i_ctime = cnvrtDosUnixTm(
-				le16_to_cpu(pfindData->LastWriteDate),
-				le16_to_cpu(pfindData->LastWriteTime));
-		AdjustForTZ(cifs_sb->tcon, tmp_inode);
+		tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
+						    pfindData->LastWriteTime,
+						    offset);
+		tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
+						    pfindData->LastAccessTime,
+						    offset);
+		tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
+						    pfindData->LastWriteTime,
+						    offset);
 		attr = le16_to_cpu(pfindData->Attributes);
 		allocation_size = le32_to_cpu(pfindData->AllocationSize);
 		end_of_file = le32_to_cpu(pfindData->DataSize);
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
  2009-05-11 20:24 ` [PATCH 01/13] cifs: have cifs_NTtimeToUnix take a little-endian arg Jeff Layton
  2009-05-11 20:24 ` [PATCH 02/13] cifs: make cnvrtDosUnixTm take a little-endian args and an offset Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:56   ` Christoph Hellwig
  2009-05-11 20:24 ` [PATCH 04/13] cifs: rename cifs_iget to cifs_root_iget Jeff Layton
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

We'll need this later when we restructure cifs_get_inode_info.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsacl.c |   25 ++++++-------------------
 1 files changed, 6 insertions(+), 19 deletions(-)

diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 57ecdc8..82fc4a9 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -555,37 +555,24 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
 
 /* Retrieve an ACL from the server */
 static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
-				       const char *path, const __u16 *pfid)
+				      const char *path, const __u16 *pfid)
 {
 	struct cifsFileInfo *open_file = NULL;
-	bool unlock_file = false;
 	int xid;
 	int rc = -EIO;
 	__u16 fid;
-	struct super_block *sb;
-	struct cifs_sb_info *cifs_sb;
 	struct cifs_ntsd *pntsd = NULL;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
 	cFYI(1, ("get mode from ACL for %s", path));
 
-	if (inode == NULL)
-		return NULL;
-
 	xid = GetXid();
-	if (pfid == NULL)
-		open_file = find_readable_file(CIFS_I(inode));
-	else
+	if (pfid)
 		fid = *pfid;
-
-	sb = inode->i_sb;
-	if (sb == NULL) {
-		FreeXid(xid);
-		return NULL;
-	}
-	cifs_sb = CIFS_SB(sb);
+	else if (inode)
+		open_file = find_readable_file(CIFS_I(inode));
 
 	if (open_file) {
-		unlock_file = true;
 		fid = open_file->netfid;
 	} else if (pfid == NULL) {
 		int oplock = 0;
@@ -603,7 +590,7 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
 
 	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
 	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
-	if (unlock_file == true) /* find_readable_file increments ref count */
+	if (open_file) /* find_readable_file increments ref count */
 		atomic_dec(&open_file->wrtPending);
 	else if (pfid == NULL) /* if opened above we have to close the handle */
 		CIFSSMBClose(xid, cifs_sb->tcon, fid);
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 04/13] cifs: rename cifs_iget to cifs_root_iget
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (2 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:24 ` [PATCH 05/13] cifs: add new cifs_fattr struct for holding cifs inode attributes in common way Jeff Layton
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

The current cifs_iget isn't suitable for anything but the root inode.
Rename it with a more appropriate name.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsfs.c |    2 +-
 fs/cifs/cifsfs.h |    2 +-
 fs/cifs/inode.c  |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 0d6d8b5..65a651c 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -145,7 +145,7 @@ cifs_read_super(struct super_block *sb, void *data,
 #endif
 	sb->s_blocksize = CIFS_MAX_MSGSIZE;
 	sb->s_blocksize_bits = 14;	/* default 2**14 = CIFS_MAX_MSGSIZE */
-	inode = cifs_iget(sb, ROOT_I);
+	inode = cifs_root_iget(sb, ROOT_I);
 
 	if (IS_ERR(inode)) {
 		rc = PTR_ERR(inode);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 051b71c..3b6a85c 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -36,7 +36,7 @@ extern void cifs_read_inode(struct inode *);
 
 /* Functions related to inodes */
 extern const struct inode_operations cifs_dir_inode_ops;
-extern struct inode *cifs_iget(struct super_block *, unsigned long);
+extern struct inode *cifs_root_iget(struct super_block *, unsigned long);
 extern int cifs_create(struct inode *, struct dentry *, int,
 		       struct nameidata *);
 extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 42d6e0f..84b7bea 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -696,7 +696,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
 }
 
 /* gets root inode */
-struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
+struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
 {
 	int xid;
 	struct cifs_sb_info *cifs_sb;
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/13] cifs: add new cifs_fattr struct for holding cifs inode attributes in common way
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (3 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 04/13] cifs: rename cifs_iget to cifs_root_iget Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 21:01   ` Christoph Hellwig
  2009-05-11 20:24 ` [PATCH 06/13] cifs: add new cifs_iget function and convert unix codepath to use it Jeff Layton
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

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.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsglob.h |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a61ab77..6a0abc0 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -472,6 +472,29 @@ struct dfs_info3_param {
 	char *node_name;
 };
 
+
+/*
+ * common struct for holding inode info when searching for or updating an
+ * inode with new info
+ */
+
+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) {
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 06/13] cifs: add new cifs_iget function and convert unix codepath to use it
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (4 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 05/13] cifs: add new cifs_fattr struct for holding cifs inode attributes in common way Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 21:06   ` Christoph Hellwig
  2009-05-11 20:24 ` [PATCH 07/13] cifs: convert posix readdir codepath to use cifs_iget Jeff Layton
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

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.

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

Fixing the unix readdir codepath will be done in a later patch.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsfs.h    |   13 ++
 fs/cifs/cifsglob.h  |    3 +
 fs/cifs/cifsproto.h |    8 +-
 fs/cifs/dir.c       |   25 ++--
 fs/cifs/inode.c     |  389 +++++++++++++++++++++++++++------------------------
 5 files changed, 247 insertions(+), 191 deletions(-)

diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 3b6a85c..029ed69 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -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;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6a0abc0..40087e6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -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;
 };
 
@@ -478,6 +479,8 @@ struct dfs_info3_param {
  * inode with new info
  */
 
+#define CIFS_FATTR_DFS_REFERRAL		0x1
+
 struct cifs_fattr {
 	u32		cf_flags;
 	u32		cf_cifsattrs;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index d542cf1..d283be5 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -98,9 +98,13 @@ 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 struct cifs_fattr *cifs_unix_basic_to_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,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 11431ed..4033a09 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -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 = NULL;
 
 	cFYI(1, ("posix open %s", full_path));
 
@@ -235,26 +236,32 @@ 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 */
 
+	fattr = cifs_unix_basic_to_fattr(presp_data, cifs_sb);
+	if (!fattr) {
+		rc = -ENOMEM;
+		goto posix_open_ret;
+	}
+
+	/* 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);
 
 posix_open_ret:
+	kfree(fattr);
 	kfree(presp_data);
 	return rc;
 }
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 84b7bea..9afd19a 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -77,127 +77,166 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
 	}
 }
 
-static void cifs_unix_info_to_inode(struct inode *inode,
-		FILE_UNIX_BASIC_INFO *info, int force_uid_gid)
+/* populate an inode with info from a cifs_fattr struct */
+void
+cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 {
-	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
-	__u64 num_of_bytes = le64_to_cpu(info->NumOfBytes);
-	__u64 end_of_file = le64_to_cpu(info->EndOfFile);
+	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+	unsigned long now = jiffies;
+
+	inode->i_atime = fattr->cf_atime;
+	inode->i_mtime = fattr->cf_mtime;
+	inode->i_ctime = fattr->cf_ctime;
+	inode->i_mode = fattr->cf_mode;
+	inode->i_rdev = fattr->cf_rdev;
+	inode->i_nlink = fattr->cf_nlink;
+	inode->i_uid = fattr->cf_uid;
+	inode->i_gid = fattr->cf_gid;
+	
+	cifs_i->cifsAttrs = fattr->cf_cifsattrs;
+	cifs_i->uniqueid = fattr->cf_uniqueid;
+
+	cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
+		 cifs_i->time, now));
+	cifs_i->time = now;
+
+	spin_lock(&inode->i_lock);
+	if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
+		/*
+		 * We can not safely change the file size here if the client
+		 * is writing to it due to potential races.
+		 */
+		i_size_write(inode, fattr->cf_eof);
+
+		/*
+		 * i_blocks is not related to (i_size / i_blksize),
+		 * but instead 512 byte (2**9) size is required for
+		 * calculating num blocks.
+		 */
+		inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
+	}
+	spin_unlock(&inode->i_lock);
 
-	inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime);
-	inode->i_mtime =
-		cifs_NTtimeToUnix(info->LastModificationTime);
-	inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
-	inode->i_mode = le64_to_cpu(info->Permissions);
+	cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL);
+}
+
+/*
+ * allocate a cifs_fattr struct and populate it with info from
+ * FILE_UNIX_BASIC_INFO. Returns pointer to populated cifs_fattr struct or
+ * NULL on error. Caller is responsible for freeing the fattr.
+ */ 
+struct cifs_fattr *
+cifs_unix_basic_to_fattr(FILE_UNIX_BASIC_INFO *info,
+			 struct cifs_sb_info *cifs_sb)
+{
+	struct cifs_fattr *fattr = kzalloc(sizeof(*fattr), GFP_KERNEL);
+
+	if (!fattr)
+		return NULL;
+
+	fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);	
+	fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
+	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+
+	fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
+	fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
+	fattr->cf_mode = le64_to_cpu(info->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;
+	fattr->cf_mode &= ~S_IFMT;
 	switch (le32_to_cpu(info->Type)) {
 	case UNIX_FILE:
-		inode->i_mode |= S_IFREG;
+		fattr->cf_mode |= S_IFREG;
+		fattr->cf_dtype = DT_REG;
 		break;
 	case UNIX_SYMLINK:
-		inode->i_mode |= S_IFLNK;
+		fattr->cf_mode |= S_IFLNK;
+		fattr->cf_dtype = DT_LNK;
 		break;
 	case UNIX_DIR:
-		inode->i_mode |= S_IFDIR;
+		fattr->cf_mode |= S_IFDIR;
+		fattr->cf_dtype = DT_DIR;
 		break;
 	case UNIX_CHARDEV:
-		inode->i_mode |= S_IFCHR;
-		inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor),
-				      le64_to_cpu(info->DevMinor) & MINORMASK);
+		fattr->cf_mode |= S_IFCHR;
+		fattr->cf_dtype = DT_CHR;
+		fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+				       le64_to_cpu(info->DevMinor) & MINORMASK);
 		break;
 	case UNIX_BLOCKDEV:
-		inode->i_mode |= S_IFBLK;
-		inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor),
-				      le64_to_cpu(info->DevMinor) & MINORMASK);
+		fattr->cf_mode |= S_IFBLK;
+		fattr->cf_dtype = DT_BLK;
+		fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+				       le64_to_cpu(info->DevMinor) & MINORMASK);
 		break;
 	case UNIX_FIFO:
-		inode->i_mode |= S_IFIFO;
+		fattr->cf_mode |= S_IFIFO;
+		fattr->cf_dtype = DT_FIFO;
 		break;
 	case UNIX_SOCKET:
-		inode->i_mode |= S_IFSOCK;
+		fattr->cf_mode |= S_IFSOCK;
+		fattr->cf_dtype = DT_SOCK;
 		break;
 	default:
 		/* safest to call it a file if we do not know */
-		inode->i_mode |= S_IFREG;
+		fattr->cf_mode |= S_IFREG;
+		fattr->cf_dtype = DT_REG;
 		cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
 		break;
 	}
 
-	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) &&
-	    !force_uid_gid)
-		inode->i_uid = cifs_sb->mnt_uid;
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
+		fattr->cf_uid = cifs_sb->mnt_uid;
 	else
-		inode->i_uid = le64_to_cpu(info->Uid);
+		fattr->cf_uid = le64_to_cpu(info->Uid);
 
-	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) &&
-	    !force_uid_gid)
-		inode->i_gid = cifs_sb->mnt_gid;
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
+		fattr->cf_gid = cifs_sb->mnt_gid;
 	else
-		inode->i_gid = le64_to_cpu(info->Gid);
+		fattr->cf_gid = le64_to_cpu(info->Gid);
 
-	inode->i_nlink = le64_to_cpu(info->Nlinks);
+	fattr->cf_nlink = le64_to_cpu(info->Nlinks);
 
-	cifsInfo->server_eof = end_of_file;
-	spin_lock(&inode->i_lock);
-	if (is_size_safe_to_change(cifsInfo, end_of_file)) {
-		/*
-		 * We can not safely change the file size here if the client
-		 * is writing to it due to potential races.
-		 */
-		i_size_write(inode, end_of_file);
-
-		/*
-		 * i_blocks is not related to (i_size / i_blksize),
-		 * but instead 512 byte (2**9) size is required for
-		 * calculating num blocks.
-		 */
-		inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
-	}
-	spin_unlock(&inode->i_lock);
+	return fattr;
 }
 
 
 /*
- *	Needed to setup inode data for the directory which is the
- *	junction to the new submount (ie to setup the fake directory
- *      which represents a DFS referral)
+ * Allocate a cifs_fattr struct and fill it with fake inode info.
+ *
+ * Needed to setup cifs_fattr data for the directory which is the
+ * junction to the new submount (ie to setup the fake directory
+ * which represents a DFS referral).
+ *
+ * Returns pointer to new cifs_fattr or NULL on error.
  */
-static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
-			       struct super_block *sb)
+static struct cifs_fattr *
+cifs_create_fake_fattr(struct super_block *sb)
 {
-	struct inode *pinode = NULL;
+	struct cifs_fattr *fattr;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
-	memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO));
+	cFYI(1, ("creating fake fattr for DFS referral"));
 
-/*	__le64 pfnd_dat->EndOfFile = cpu_to_le64(0);
-	__le64 pfnd_dat->NumOfBytes = cpu_to_le64(0);
-	__u64 UniqueId = 0;  */
-	pfnd_dat->LastStatusChange =
-		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-	pfnd_dat->LastAccessTime =
-		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-	pfnd_dat->LastModificationTime =
-		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-	pfnd_dat->Type = cpu_to_le32(UNIX_DIR);
-	pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU);
-	pfnd_dat->Nlinks = cpu_to_le64(2);
-	if (sb->s_root)
-		pinode = sb->s_root->d_inode;
-	if (pinode == NULL)
-		return;
-
-	/* fill in default values for the remaining based on root
-	   inode since we can not query the server for this inode info */
-	pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev));
-	pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev));
-	pfnd_dat->Uid = cpu_to_le64(pinode->i_uid);
-	pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
+	fattr = kzalloc(sizeof(*fattr), GFP_KERNEL);
+	if (!fattr)
+		return NULL;
+
+	fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
+	fattr->cf_uid = cifs_sb->mnt_uid;
+	fattr->cf_gid = cifs_sb->mnt_gid;
+	fattr->cf_atime = CURRENT_TIME;
+	fattr->cf_ctime = CURRENT_TIME;
+	fattr->cf_mtime = CURRENT_TIME;
+	fattr->cf_nlink = 2;
+
+	fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
+
+	return fattr;
 }
 
 /**
@@ -248,13 +287,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 {
 	int rc = 0;
 	FILE_UNIX_BASIC_INFO find_data;
+	struct cifs_fattr *fattr = NULL;
 	struct cifsTconInfo *pTcon;
-	struct inode *inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	bool is_dfs_referral = false;
-	struct cifsInodeInfo *cifsInfo;
-	__u64 num_of_bytes;
-	__u64 end_of_file;
 
 	pTcon = cifs_sb->tcon;
 	cFYI(1, ("Getting info on %s", full_path));
@@ -263,47 +298,28 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 	rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data,
 				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
-	if (rc == -EREMOTE && !is_dfs_referral) {
-		is_dfs_referral = true;
-		cFYI(DBG2, ("DFS ref"));
-		/* for DFS, server does not give us real inode data */
-		fill_fake_finddataunix(&find_data, sb);
-		rc = 0;
-	} else if (rc)
-		goto cgiiu_exit;
 
-	num_of_bytes = le64_to_cpu(find_data.NumOfBytes);
-	end_of_file = le64_to_cpu(find_data.EndOfFile);
+	if (!rc)
+		fattr = cifs_unix_basic_to_fattr(&find_data, cifs_sb);
+	else if (rc == -EREMOTE)
+		fattr = cifs_create_fake_fattr(sb);
+	else
+		return rc;
 
-	/* get new inode */
+	if (!fattr)
+		return -ENOMEM;
+
+	rc = 0;
 	if (*pinode == NULL) {
-		__u64 unique_id = le64_to_cpu(find_data.UniqueId);
-		*pinode = cifs_new_inode(sb, &unique_id);
-		if (*pinode == NULL) {
+		/* get new inode */
+		*pinode = cifs_iget(sb, fattr);
+		if (!*pinode)
 			rc = -ENOMEM;
-			goto cgiiu_exit;
-		}
+	} else {
+		/* we already have inode, update it */
+		cifs_fattr_to_inode(*pinode, fattr);
 	}
 
-	inode = *pinode;
-	cifsInfo = CIFS_I(inode);
-
-	cFYI(1, ("Old time %ld", cifsInfo->time));
-	cifsInfo->time = jiffies;
-	cFYI(1, ("New time %ld", cifsInfo->time));
-	/* this is ok to set on every inode revalidate */
-	atomic_set(&cifsInfo->inUse, 1);
-
-	cifs_unix_info_to_inode(inode, &find_data, 0);
-
-	if (num_of_bytes < end_of_file)
-		cFYI(1, ("allocation size less than end of file"));
-	cFYI(1, ("Size %ld and blocks %llu",
-		(unsigned long) inode->i_size,
-		(unsigned long long)inode->i_blocks));
-
-	cifs_set_ops(inode, is_dfs_referral);
-cgiiu_exit:
 	return rc;
 }
 
@@ -695,33 +711,83 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
 	return full_path;
 }
 
+static int
+cifs_find_inode(struct inode *inode, void *opaque)
+{
+	struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
+
+	if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
+		return 0;
+
+	return 1;
+}
+
+static int
+cifs_init_inode(struct inode *inode, void *opaque)
+{
+	struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
+
+	CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
+	return 0;
+}
+
+/* Given fattrs, get a corresponding inode */
+struct inode *
+cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
+{
+	unsigned long hash;
+	struct inode *inode;
+
+	cFYI(1,("looking for uniqueid=%llu\n", fattr->cf_uniqueid));
+
+	/* hash down to 32-bits on 32-bit arch */
+	hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
+
+	inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
+
+	/* we have fattrs in hand, update the inode */
+	if (inode) {
+		cifs_fattr_to_inode(inode, fattr);
+		if (inode->i_state & I_NEW) {
+			inode->i_ino = hash;
+			unlock_new_inode(inode);
+		}
+	}
+
+	return inode;
+}
+
 /* gets root inode */
 struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
 {
 	int xid;
 	struct cifs_sb_info *cifs_sb;
-	struct inode *inode;
+	struct inode *inode = NULL;
 	long rc;
 	char *full_path;
 
-	inode = iget_locked(sb, ino);
-	if (!inode)
-		return ERR_PTR(-ENOMEM);
-	if (!(inode->i_state & I_NEW))
-		return inode;
-
-	cifs_sb = CIFS_SB(inode->i_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)
-		rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
-						xid);
-	else
+	if (cifs_sb->tcon->unix_ext) {
+		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
+		if (!inode)
+			return ERR_PTR(-ENOMEM);
+	} else {
+		inode = iget_locked(sb, ino);
+		if (!inode)
+			return ERR_PTR(-ENOMEM);
+		if (!(inode->i_state & I_NEW))
+			return inode;
+
 		rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
 						xid, NULL);
+		unlock_new_inode(inode);
+	}
+
 	if (rc && cifs_sb->tcon->ipc) {
 		cFYI(1, ("ipc connection - fake read inode"));
 		inode->i_mode |= S_IFDIR;
@@ -737,7 +803,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
 		return ERR_PTR(rc);
 	}
 
-	unlock_new_inode(inode);
 
 	kfree(full_path);
 	/* can not call macro FreeXid here since in a void func
@@ -1062,44 +1127,6 @@ out_reval:
 	return rc;
 }
 
-void posix_fill_in_inode(struct inode *tmp_inode,
-	FILE_UNIX_BASIC_INFO *pData, int isNewInode)
-{
-	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
-	loff_t local_size;
-	struct timespec local_mtime;
-
-	cifsInfo->time = jiffies;
-	atomic_inc(&cifsInfo->inUse);
-
-	/* save mtime and size */
-	local_mtime = tmp_inode->i_mtime;
-	local_size  = tmp_inode->i_size;
-
-	cifs_unix_info_to_inode(tmp_inode, pData, 1);
-	cifs_set_ops(tmp_inode, false);
-
-	if (!S_ISREG(tmp_inode->i_mode))
-		return;
-
-	/*
-	 * No sense invalidating pages for new inode
-	 * since we we have not started caching
-	 * readahead file data yet.
-	 */
-	if (isNewInode)
-		return;
-
-	if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
-		(local_size == tmp_inode->i_size)) {
-		cFYI(1, ("inode exists but unchanged"));
-	} else {
-		/* file may have changed on server */
-		cFYI(1, ("invalidate inode, readdir detected change"));
-		invalidate_remote_inode(tmp_inode);
-	}
-}
-
 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
 {
 	int rc = 0, tmprc;
@@ -1108,6 +1135,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct inode *newinode = NULL;
+	struct cifs_fattr *fattr = NULL;
 
 	cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
 
@@ -1146,7 +1174,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
 			cFYI(1, ("posix mkdir returned 0x%x", rc));
 			d_drop(direntry);
 		} else {
-			__u64 unique_id;
 			if (pInfo->Type == cpu_to_le32(-1)) {
 				/* no return info, go query for it */
 				kfree(pInfo);
@@ -1160,20 +1187,21 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
 			else
 				direntry->d_op = &cifs_dentry_ops;
 
-			unique_id = le64_to_cpu(pInfo->UniqueId);
-			newinode = cifs_new_inode(inode->i_sb, &unique_id);
-			if (newinode == NULL) {
+			fattr = cifs_unix_basic_to_fattr(pInfo, cifs_sb);
+			if (!fattr) {
+				kfree(pInfo);
+				goto mkdir_get_info;
+			}
+
+			newinode = cifs_iget(inode->i_sb, fattr);
+			kfree(fattr);
+			if (!newinode) {
 				kfree(pInfo);
 				goto mkdir_get_info;
 			}
 
-			newinode->i_nlink = 2;
 			d_instantiate(direntry, newinode);
 
-			/* we already checked in POSIXCreate whether
-			   frame was long enough */
-			posix_fill_in_inode(direntry->d_inode,
-					pInfo, 1 /* NewInode */);
 #ifdef CONFIG_CIFS_DEBUG2
 			cFYI(1, ("instantiated dentry %p %s to inode %p",
 				direntry, direntry->d_name.name, newinode));
@@ -1618,6 +1646,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	if (!err) {
 		generic_fillattr(dentry->d_inode, stat);
 		stat->blksize = CIFS_MAX_MSGSIZE;
+		stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
 	}
 	return err;
 }
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 07/13] cifs: convert posix readdir codepath to use cifs_iget
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (5 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 06/13] cifs: add new cifs_iget function and convert unix codepath to use it Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:24 ` [PATCH 08/13] cifs: convert cifs_get_inode_info " Jeff Layton
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

Add a new function that converts FILE_INFO_UNIX to fattr, and a readdir
lookup function that spawns dentries.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/readdir.c |  301 +++++++++++++++++++++++++++--------------------------
 1 files changed, 154 insertions(+), 147 deletions(-)

diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 86d0055..c86b293 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -63,6 +63,55 @@ static inline void dump_cifs_file_struct(struct file *file, char *label)
 }
 #endif /* DEBUG2 */
 
+/*
+ * Find the dentry that matches "name". If there isn't one, create
+ * one. If it's a negative dentry, then drop it and recreate it.
+ */
+static struct dentry *
+cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
+		    struct cifs_fattr *fattr)
+{
+	struct dentry *dentry, *alias;
+	struct inode *inode;
+	struct super_block *sb = parent->d_inode->i_sb;
+
+	cFYI(1, ("For %s", name->name));
+
+	dentry = d_lookup(parent, name);
+	if (dentry) {
+		/* BB: check for inode number change */
+		if (dentry->d_inode != NULL)
+			return dentry;
+		d_drop(dentry);
+		dput(dentry);
+	}
+
+	dentry = d_alloc(parent, name);
+	if (dentry == NULL)
+		return NULL;
+
+	inode = cifs_iget(sb, fattr);
+	if (IS_ERR(inode)) {
+		dput(dentry);
+		return NULL;
+	}
+
+	if (CIFS_SB(sb)->tcon->nocase)
+		dentry->d_op = &cifs_ci_dentry_ops;
+	else
+		dentry->d_op = &cifs_dentry_ops;
+
+	alias = d_materialise_unique(dentry, inode);
+	if (alias != NULL) {
+		dput(dentry);
+		if (IS_ERR(alias))
+			return NULL;
+		dentry = alias;
+	}
+
+	return dentry;
+}
+
 /* 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 */
 static int
@@ -76,7 +125,6 @@ construct_dentry(struct qstr *qstring, struct file *file,
 
 	cFYI(1, ("For %s", qstring->name));
 
-	qstring->hash = full_name_hash(qstring->name, qstring->len);
 	tmp_dentry = d_lookup(file->f_path.dentry, qstring);
 	if (tmp_dentry) {
 		/* BB: overwrite old name? i.e. tmp_dentry->d_name and
@@ -299,138 +347,78 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
 	}
 }
 
-static void unix_fill_in_inode(struct inode *tmp_inode,
-	FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode)
+/*
+ * Allocate a cifs_fattr and fill it with info from FILE_UNIX_BASIC. Returns
+ * pointer to the cifs_fattr or NULL on error. Caller is responsible for
+ * freeing the cifs_fattr.
+ */
+static struct cifs_fattr *
+cifs_unix_info_to_fattr(FILE_UNIX_INFO *info, struct cifs_sb_info *cifs_sb)
 {
-	loff_t local_size;
-	struct timespec local_mtime;
+	struct cifs_fattr *fattr;
 
-	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
-	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
-
-	__u32 type = le32_to_cpu(pfindData->Type);
-	__u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
-	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
-	cifsInfo->time = jiffies;
-	atomic_inc(&cifsInfo->inUse);
+	fattr = kzalloc(sizeof(*fattr), GFP_KERNEL);
+	if (!fattr)
+		return NULL;
 
-	/* save mtime and size */
-	local_mtime = tmp_inode->i_mtime;
-	local_size  = tmp_inode->i_size;
+	fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
+	fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
 
-	tmp_inode->i_atime =
-	    cifs_NTtimeToUnix(pfindData->LastAccessTime);
-	tmp_inode->i_mtime =
-	    cifs_NTtimeToUnix(pfindData->LastModificationTime);
-	tmp_inode->i_ctime =
-	    cifs_NTtimeToUnix(pfindData->LastStatusChange);
-
-	tmp_inode->i_mode = le64_to_cpu(pfindData->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;
-	if (type == UNIX_FILE) {
-		*pobject_type = DT_REG;
-		tmp_inode->i_mode |= S_IFREG;
-	} else if (type == UNIX_SYMLINK) {
-		*pobject_type = DT_LNK;
-		tmp_inode->i_mode |= S_IFLNK;
-	} else if (type == UNIX_DIR) {
-		*pobject_type = DT_DIR;
-		tmp_inode->i_mode |= S_IFDIR;
-	} else if (type == UNIX_CHARDEV) {
-		*pobject_type = DT_CHR;
-		tmp_inode->i_mode |= S_IFCHR;
-		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
-				le64_to_cpu(pfindData->DevMinor) & MINORMASK);
-	} else if (type == UNIX_BLOCKDEV) {
-		*pobject_type = DT_BLK;
-		tmp_inode->i_mode |= S_IFBLK;
-		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
-				le64_to_cpu(pfindData->DevMinor) & MINORMASK);
-	} else if (type == UNIX_FIFO) {
-		*pobject_type = DT_FIFO;
-		tmp_inode->i_mode |= S_IFIFO;
-	} else if (type == UNIX_SOCKET) {
-		*pobject_type = DT_SOCK;
-		tmp_inode->i_mode |= S_IFSOCK;
-	} else {
+	fattr->cf_mode = le64_to_cpu(info->Permissions) & ~S_IFMT;
+	switch (le32_to_cpu(info->Type)) {
+	case UNIX_FILE:
+		fattr->cf_mode |= S_IFREG;
+		fattr->cf_dtype = DT_REG;
+		break;
+	case UNIX_SYMLINK:
+		fattr->cf_mode |= S_IFLNK;
+		fattr->cf_dtype = DT_LNK;
+		break;
+	case UNIX_DIR:
+		fattr->cf_mode |= S_IFDIR;
+		fattr->cf_dtype = DT_DIR;
+		break;
+	case UNIX_CHARDEV:
+		fattr->cf_mode |= S_IFCHR;
+		fattr->cf_dtype = DT_CHR;
+		fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+				       le64_to_cpu(info->DevMinor) & MINORMASK);
+		break;
+	case UNIX_BLOCKDEV:
+		fattr->cf_mode |= S_IFBLK;
+		fattr->cf_dtype = DT_BLK;
+		fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+				       le64_to_cpu(info->DevMinor) & MINORMASK);
+		break;
+	case UNIX_FIFO:
+		fattr->cf_mode |= S_IFIFO;
+		fattr->cf_dtype = DT_FIFO;
+		break;
+	case UNIX_SOCKET:
+		fattr->cf_mode |= S_IFSOCK;
+		fattr->cf_dtype = DT_SOCK;
+		break;
+	default:
 		/* safest to just call it a file */
-		*pobject_type = DT_REG;
-		tmp_inode->i_mode |= S_IFREG;
-		cFYI(1, ("unknown inode type %d", type));
+		fattr->cf_mode |= S_IFREG;
+		fattr->cf_dtype = DT_REG;
+		cFYI(1, ("unknown inode type %d", le32_to_cpu(info->Type)));
 	}
 
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
-		tmp_inode->i_uid = cifs_sb->mnt_uid;
+		fattr->cf_uid = cifs_sb->mnt_uid;
 	else
-		tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
+		fattr->cf_uid = le64_to_cpu(info->Uid);
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
-		tmp_inode->i_gid = cifs_sb->mnt_gid;
+		fattr->cf_gid = cifs_sb->mnt_gid;
 	else
-		tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
-	tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
-
-	cifsInfo->server_eof = end_of_file;
-	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
-		client is writing to it due to potential races */
-		i_size_write(tmp_inode, end_of_file);
-
-	/* 512 bytes (2**9) is the fake blocksize that must be used */
-	/* for this calculation, not the real blocksize */
-		tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
-	}
-	spin_unlock(&tmp_inode->i_lock);
-
-	if (S_ISREG(tmp_inode->i_mode)) {
-		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)
-				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)
-			tmp_inode->i_fop = &cifs_file_nobrl_ops;
-		else
-			tmp_inode->i_fop = &cifs_file_ops;
+		fattr->cf_gid = le64_to_cpu(info->Gid);
 
-		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;
+	fattr->cf_nlink = le64_to_cpu(info->Nlinks);
+	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
 
-		if (isNewInode)
-			return; /* No sense invalidating pages for new inode
-				   since we have not started caching readahead
-				   file data for it yet */
-
-		if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
-			(local_size == tmp_inode->i_size)) {
-			cFYI(1, ("inode exists but unchanged"));
-		} else {
-			/* file may have changed on server */
-			cFYI(1, ("invalidate inode, readdir detected change"));
-			invalidate_remote_inode(tmp_inode);
-		}
-	} else if (S_ISDIR(tmp_inode->i_mode)) {
-		cFYI(1, ("Directory inode"));
-		tmp_inode->i_op = &cifs_dir_inode_ops;
-		tmp_inode->i_fop = &cifs_dir_ops;
-	} else if (S_ISLNK(tmp_inode->i_mode)) {
-		cFYI(1, ("Symbolic Link inode"));
-		tmp_inode->i_op = &cifs_symlink_inode_ops;
-/* tmp_inode->i_fop = *//* do not need to set to anything */
-	} else {
-		cFYI(1, ("Special inode"));
-		init_special_inode(tmp_inode, tmp_inode->i_mode,
-				   tmp_inode->i_rdev);
-	}
+	return fattr;
 }
 
 /* BB eventually need to add the following helper function to
@@ -937,6 +925,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
 	struct cifs_sb_info *cifs_sb;
 	struct inode *tmp_inode;
 	struct dentry *tmp_dentry;
+	struct cifs_fattr *fattr = NULL;
 
 	/* get filename and len into qstring */
 	/* get dentry */
@@ -967,36 +956,52 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
 		return rc;
 
 	/* 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 (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
+		fattr = cifs_unix_info_to_fattr((FILE_UNIX_INFO *) pfindEntry,
+						cifs_sb);
+		if (!fattr) {
+			rc = -ENOMEM;
+			goto out;
+		}
 
-	if ((tmp_inode == NULL) || (tmp_dentry == NULL))
-		return -ENOMEM;
+		tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring,
+						 fattr);
+		if (!tmp_dentry) {
+			rc = -ENOMEM;
+			goto out;
+		}
 
-	/* we pass in rc below, indicating whether it is a new inode,
-	   so we can figure out whether to invalidate the inode cached
-	   data if the file has changed */
-	if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
-		unix_fill_in_inode(tmp_inode,
-				   (FILE_UNIX_INFO *)pfindEntry,
-				   &obj_type, rc);
-	else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
-		fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
-				pfindEntry, &obj_type, rc);
-	else
-		fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);
+		obj_type = fattr->cf_dtype;
+	} else {
+		if (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 (rc) /* new inode - needs to be tied to dentry */ {
-		d_instantiate(tmp_dentry, tmp_inode);
-		if (rc == 2)
-			d_rehash(tmp_dentry);
-	}
+		if ((tmp_inode == NULL) || (tmp_dentry == NULL)) {
+			rc = -ENOMEM;
+			goto out;
+		}
 
+		/* we pass in rc below, indicating whether it is a new inode,
+		 * so we can figure out whether to invalidate the inode cached
+		 * data if the file has changed
+		 */
+		if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
+			fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc);
+		else
+			fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc);
+
+		/* new inode - needs to be tied to dentry */
+		if (rc) {
+			d_instantiate(tmp_dentry, tmp_inode);
+			if (rc == 2)
+				d_rehash(tmp_dentry);
+		}
+	}
 
 	rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
 		     tmp_inode->i_ino, obj_type);
@@ -1008,6 +1013,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
 		rc = -EOVERFLOW;
 	}
 
+out:
+	kfree(fattr);
 	dput(tmp_dentry);
 	return rc;
 }
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 08/13] cifs: convert cifs_get_inode_info to use cifs_iget
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (6 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 07/13] cifs: convert posix readdir codepath to use cifs_iget Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:24 ` [PATCH 09/13] cifs: convert non-posix readdir codepath " Jeff Layton
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

Rather than allocating an inode and filling it out, have
cifs_get_inode_info fill out a cifs_fattr and call cifs_iget.

This means a pretty hefty reorganization of cifs_get_inode_info.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsacl.c   |   25 ++--
 fs/cifs/cifsglob.h  |    1 +
 fs/cifs/cifsproto.h |    4 +-
 fs/cifs/inode.c     |  360 +++++++++++++++++++++++----------------------------
 4 files changed, 175 insertions(+), 215 deletions(-)

diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 82fc4a9..3f144bc 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -327,7 +327,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
 
 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 		       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
-		       struct inode *inode)
+		       struct cifs_fattr *fattr)
 {
 	int i;
 	int num_aces = 0;
@@ -340,7 +340,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 	if (!pdacl) {
 		/* no DACL in the security descriptor, set
 		   all the permissions for user/group/other */
-		inode->i_mode |= S_IRWXUGO;
+		fattr->cf_mode |= S_IRWXUGO;
 		return;
 	}
 
@@ -357,7 +357,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 	/* reset rwx permissions for user/group/other.
 	   Also, if num_aces is 0 i.e. DACL has no ACEs,
 	   user/group/other have no permissions */
-	inode->i_mode &= ~(S_IRWXUGO);
+	fattr->cf_mode &= ~(S_IRWXUGO);
 
 	acl_base = (char *)pdacl;
 	acl_size = sizeof(struct cifs_acl);
@@ -379,17 +379,17 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 			if (compare_sids(&(ppace[i]->sid), pownersid))
 				access_flags_to_mode(ppace[i]->access_req,
 						     ppace[i]->type,
-						     &(inode->i_mode),
+						     &(fattr->cf_mode),
 						     &user_mask);
 			if (compare_sids(&(ppace[i]->sid), pgrpsid))
 				access_flags_to_mode(ppace[i]->access_req,
 						     ppace[i]->type,
-						     &(inode->i_mode),
+						     &(fattr->cf_mode),
 						     &group_mask);
 			if (compare_sids(&(ppace[i]->sid), &sid_everyone))
 				access_flags_to_mode(ppace[i]->access_req,
 						     ppace[i]->type,
-						     &(inode->i_mode),
+						     &(fattr->cf_mode),
 						     &other_mask);
 
 /*			memcpy((void *)(&(cifscred->aces[i])),
@@ -464,7 +464,7 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 
 /* Convert CIFS ACL to POSIX form */
 static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
-			  struct inode *inode)
+			  struct cifs_fattr *fattr)
 {
 	int rc;
 	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
@@ -472,7 +472,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
 	char *end_of_acl = ((char *)pntsd) + acl_len;
 	__u32 dacloffset;
 
-	if ((inode == NULL) || (pntsd == NULL))
+	if (pntsd == NULL)
 		return -EIO;
 
 	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
@@ -497,7 +497,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
 
 	if (dacloffset)
 		parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
-			   group_sid_ptr, inode);
+			   group_sid_ptr, fattr);
 	else
 		cFYI(1, ("no ACL")); /* BB grant all or default perms? */
 
@@ -508,7 +508,6 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
 	memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
 			sizeof(struct cifs_sid)); */
 
-
 	return 0;
 }
 
@@ -655,7 +654,9 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
 }
 
 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
-void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
+void
+cifs_acl_to_fattr(struct cifs_fattr *fattr, struct inode *inode,
+		  const char *path, const __u16 *pfid)
 {
 	struct cifs_ntsd *pntsd = NULL;
 	u32 acllen = 0;
@@ -666,7 +667,7 @@ void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
 
 	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
 	if (pntsd)
-		rc = parse_sec_desc(pntsd, acllen, inode);
+		rc = parse_sec_desc(pntsd, acllen, fattr);
 	if (rc)
 		cFYI(1, ("parse sec desc failed rc = %d", rc));
 
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 40087e6..a5e55e7 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -480,6 +480,7 @@ struct dfs_info3_param {
  */
 
 #define CIFS_FATTR_DFS_REFERRAL		0x1
+#define CIFS_FATTR_DELETE_PENDING	0x2
 
 struct cifs_fattr {
 	u32		cf_flags;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index d283be5..d572647 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -112,8 +112,8 @@ extern int cifs_get_inode_info(struct inode **pinode,
 extern int cifs_get_inode_info_unix(struct inode **pinode,
 			const unsigned char *search_path,
 			struct super_block *sb, int xid);
-extern void acl_to_uid_mode(struct inode *inode, const char *path,
-			    const __u16 *pfid);
+extern void cifs_acl_to_fattr(struct cifs_fattr *fattr, struct inode *inode,
+			    const char *path, const __u16 *pfid);
 extern int mode_to_acl(struct inode *inode, const char *path, __u64);
 
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 9afd19a..2b1c0cf 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -82,16 +82,21 @@ void
 cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 {
 	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 	unsigned long now = jiffies;
 
 	inode->i_atime = fattr->cf_atime;
 	inode->i_mtime = fattr->cf_mtime;
 	inode->i_ctime = fattr->cf_ctime;
-	inode->i_mode = fattr->cf_mode;
 	inode->i_rdev = fattr->cf_rdev;
 	inode->i_nlink = fattr->cf_nlink;
 	inode->i_uid = fattr->cf_uid;
 	inode->i_gid = fattr->cf_gid;
+
+	/* if dynperm is set, don't clobber existing mode */
+	if (inode->i_state & I_NEW ||
+	    !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
+		inode->i_mode = fattr->cf_mode;
 	
 	cifs_i->cifsAttrs = fattr->cf_cifsattrs;
 	cifs_i->uniqueid = fattr->cf_uniqueid;
@@ -100,12 +105,12 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 		 cifs_i->time, now));
 	cifs_i->time = now;
 
+	/*
+	 * Can't safely change the file size here if the client is writing to
+	 * it due to potential races.
+	 */
 	spin_lock(&inode->i_lock);
 	if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
-		/*
-		 * We can not safely change the file size here if the client
-		 * is writing to it due to potential races.
-		 */
 		i_size_write(inode, fattr->cf_eof);
 
 		/*
@@ -323,9 +328,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 	return rc;
 }
 
-static int decode_sfu_inode(struct inode *inode, __u64 size,
-			    const unsigned char *path,
-			    struct cifs_sb_info *cifs_sb, int xid)
+static int
+cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
+	      struct cifs_sb_info *cifs_sb, int xid)
 {
 	int rc;
 	int oplock = 0;
@@ -337,10 +342,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
 
 	pbuf = buf;
 
-	if (size == 0) {
-		inode->i_mode |= S_IFIFO;
+	fattr->cf_mode &= ~S_IFMT;
+
+	if (fattr->cf_eof == 0) {
+		fattr->cf_mode |= S_IFIFO;
+		fattr->cf_dtype = DT_FIFO;
 		return 0;
-	} else if (size < 8) {
+	} else if (fattr->cf_eof < 8) {
+		fattr->cf_mode |= S_IFREG;
+		fattr->cf_dtype = DT_REG;
 		return -EINVAL;	 /* EOPNOTSUPP? */
 	}
 
@@ -352,42 +362,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
 	if (rc == 0) {
 		int buf_type = CIFS_NO_BUFFER;
 			/* Read header */
-		rc = CIFSSMBRead(xid, pTcon,
-				 netfid,
+		rc = CIFSSMBRead(xid, pTcon, 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"));
-				inode->i_mode |= S_IFBLK;
+				fattr->cf_mode |= S_IFBLK;
+				fattr->cf_dtype = DT_BLK;
 				if (bytes_read == 24) {
 					/* we have enough to decode dev num */
 					__u64 mjr; /* major */
 					__u64 mnr; /* minor */
 					mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
 					mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
-					inode->i_rdev = MKDEV(mjr, mnr);
+					fattr->cf_rdev = MKDEV(mjr, mnr);
 				}
 			} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
 				cFYI(1, ("Char device"));
-				inode->i_mode |= S_IFCHR;
+				fattr->cf_mode |= S_IFCHR;
+				fattr->cf_dtype = DT_CHR;
 				if (bytes_read == 24) {
 					/* we have enough to decode dev num */
 					__u64 mjr; /* major */
 					__u64 mnr; /* minor */
 					mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
 					mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
-					inode->i_rdev = MKDEV(mjr, mnr);
+					fattr->cf_rdev = MKDEV(mjr, mnr);
 				}
 			} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
 				cFYI(1, ("Symlink"));
-				inode->i_mode |= S_IFLNK;
+				fattr->cf_mode |= S_IFLNK;
+				fattr->cf_dtype = DT_LNK;
 			} else {
-				inode->i_mode |= S_IFREG; /* file? */
+				fattr->cf_mode |= S_IFREG; /* file? */
+				fattr->cf_dtype = DT_REG;
 				rc = -EOPNOTSUPP;
 			}
 		} else {
-			inode->i_mode |= S_IFREG; /* then it is a file */
+			fattr->cf_mode |= S_IFREG; /* then it is a file */
+			fattr->cf_dtype = DT_REG;
 			rc = -EOPNOTSUPP; /* or some unknown SFU type */
 		}
 		CIFSSMBClose(xid, pTcon, netfid);
@@ -397,9 +411,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
 
 #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID)  /* SETFILEBITS valid bits */
 
-static int get_sfu_mode(struct inode *inode,
-			const unsigned char *path,
-			struct cifs_sb_info *cifs_sb, int xid)
+/*
+ * Fetch mode bits as provided by SFU.
+ *
+ * BB: Doesn't this clobber the type bit we got from cifs_sfu_type ?
+ */
+static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
+			 struct cifs_sb_info *cifs_sb, int xid)
 {
 #ifdef CONFIG_CIFS_XATTR
 	ssize_t rc;
@@ -407,68 +425,90 @@ static int get_sfu_mode(struct inode *inode,
 	__u32 mode;
 
 	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);
+			    ea_value, 4 /* size of buf */, cifs_sb->local_nls,
+			    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 = (mode &  SFBITS_MASK) | inode->i_mode;
+		fattr->cf_mode &= ~SFBITS_MASK;
+		cFYI(1, ("special bits 0%o org mode 0%o", mode,
+			 fattr->cf_mode));
+		fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
 		cFYI(1, ("special mode bits 0%o", mode));
-		return 0;
-	} else {
-		return 0;
 	}
+
+	return 0;
 #else
 	return -EOPNOTSUPP;
 #endif
 }
 
 /*
- *	Needed to setup inode data for the directory which is the
- *	junction to the new submount (ie to setup the fake directory
- *      which represents a DFS referral)
+ * Allocate a cifs_fattr struct and populate it with info from FILE_ALL_INFO
+ * and the cifs_sb. Returns a pointer to the cifs_fattr struct or NULL on
+ * error. The caller is responsible for freeing the struct.
  */
-static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat,
-			       struct super_block *sb)
+static struct cifs_fattr *
+cifs_all_info_to_fattr(FILE_ALL_INFO *info, struct cifs_sb_info *cifs_sb,
+		       bool adjust_tz)
 {
-	memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO));
-
-/*	__le64 pfnd_dat->AllocationSize = cpu_to_le64(0);
-	__le64 pfnd_dat->EndOfFile = cpu_to_le64(0);
-	__u8 pfnd_dat->DeletePending = 0;
-	__u8 pfnd_data->Directory = 0;
-	__le32 pfnd_dat->EASize = 0;
-	__u64 pfnd_dat->IndexNumber = 0;
-	__u64 pfnd_dat->IndexNumber1 = 0;  */
-	pfnd_dat->CreationTime =
-		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-	pfnd_dat->LastAccessTime =
-		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-	pfnd_dat->LastWriteTime =
-		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-	pfnd_dat->ChangeTime =
-		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-	pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY);
-	pfnd_dat->NumberOfLinks = cpu_to_le32(2);
+	struct cifs_fattr *fattr = kzalloc(sizeof(*fattr), GFP_KERNEL);
+
+	if (!fattr)
+		return NULL;
+
+	fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
+	if (info->DeletePending)
+		fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
+
+	if (info->LastAccessTime)
+		fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+	else
+		fattr->cf_atime = CURRENT_TIME;
+
+	fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
+	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_eof = le64_to_cpu(info->EndOfFile);
+	fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
+
+	if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
+		fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
+		fattr->cf_dtype = DT_DIR;
+	} else {
+		fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
+		fattr->cf_dtype = DT_REG;
+	}
+
+	/* clear write bits if ATTR_READONLY is set */
+	if (fattr->cf_cifsattrs & ATTR_READONLY)
+		fattr->cf_mode &= ~(S_IWUGO);
+
+	fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
+
+	fattr->cf_uid = cifs_sb->mnt_uid;
+	fattr->cf_gid = cifs_sb->mnt_gid;
+
+	return fattr;
 }
 
 int cifs_get_inode_info(struct inode **pinode,
 	const unsigned char *full_path, FILE_ALL_INFO *pfindData,
 	struct super_block *sb, int xid, const __u16 *pfid)
 {
-	int rc = 0;
-	__u32 attr;
-	struct cifsInodeInfo *cifsInfo;
+	int rc = 0, tmprc;
 	struct cifsTconInfo *pTcon;
-	struct inode *inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 	char *buf = NULL;
 	bool adjustTZ = false;
-	bool is_dfs_referral = false;
-	umode_t default_mode;
+	struct cifs_fattr *fattr = NULL;
 
 	pTcon = cifs_sb->tcon;
 	cFYI(1, ("Getting info on %s", full_path));
@@ -503,166 +543,91 @@ int cifs_get_inode_info(struct inode **pinode,
 			adjustTZ = true;
 		}
 	}
-	/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
-	if (rc == -EREMOTE) {
-		is_dfs_referral = true;
-		fill_fake_finddata(pfindData, sb);
+
+	if (!rc) {
+		fattr = cifs_all_info_to_fattr((FILE_ALL_INFO *) pfindData,
+					       cifs_sb, adjustTZ);
+	} else if (rc == -EREMOTE) {
+		fattr = cifs_create_fake_fattr(sb);
 		rc = 0;
-	} else if (rc)
+	} else {
 		goto cgii_exit;
+	}
 
-	attr = le32_to_cpu(pfindData->Attributes);
+	if (!fattr) {
+		rc = -ENOMEM;
+		goto cgii_exit;
+	}
 
-	/* get new inode */
+	/*
+	 * If an inode wasn't passed in, then get the inode number
+	 *
+	 * Is an i_ino of zero legal? Can we use that to check if the server
+	 * supports returning inode numbers?  Are there other sanity checks we
+	 * can use to ensure that the server is really filling in that field?
+	 *
+	 * We can not use the IndexNumber field by default from Windows or
+	 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
+	 * CIFS spec claims that this value is unique within the scope of a
+	 * share, and the windows docs hint that it's actually unique
+	 * per-machine.
+	 *
+	 * There may be higher info levels that work but are there Windows
+	 * server or network appliances for which IndexNumber field is not
+	 * guaranteed unique?
+	 */
 	if (*pinode == NULL) {
-		__u64 inode_num;
-		__u64 *pinum = &inode_num;
-
-		/* Is an i_ino of zero legal? Can we use that to check
-		   if the server supports returning inode numbers?  Are
-		   there other sanity checks we can use to ensure that
-		   the server is really filling in that field? */
-
-		/* We can not use the IndexNumber field by default from
-		   Windows or Samba (in ALL_INFO buf) but we can request
-		   it explicitly.  It may not be unique presumably if
-		   the server has multiple devices mounted under one share */
-
-		/* There may be higher info levels that work but are
-		   there Windows server or network appliances for which
-		   IndexNumber field is not guaranteed unique? */
-
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
 			int rc1 = 0;
 
 			rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
-					full_path, pinum,
+					full_path, &fattr->cf_uniqueid,
 					cifs_sb->local_nls,
 					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			if (rc1) {
-				cFYI(1, ("GetSrvInodeNum rc %d", rc1));
-				pinum = NULL;
 				/* BB EOPNOSUPP disable SERVER_INUM? */
+				cFYI(1, ("GetSrvInodeNum rc %d", rc1));
+				fattr->cf_uniqueid = iunique(sb, ROOT_I);
 			}
 		} else {
-			pinum = NULL;
+			fattr->cf_uniqueid = iunique(sb, ROOT_I);
 		}
-
-		*pinode = cifs_new_inode(sb, pinum);
-		if (*pinode == NULL) {
-			rc = -ENOMEM;
-			goto cgii_exit;
-		}
-	}
-	inode = *pinode;
-	cifsInfo = CIFS_I(inode);
-	cifsInfo->cifsAttrs = attr;
-	cifsInfo->delete_pending = pfindData->DeletePending ? true : false;
-	cFYI(1, ("Old time %ld", cifsInfo->time));
-	cifsInfo->time = jiffies;
-	cFYI(1, ("New time %ld", cifsInfo->time));
-
-	/* blksize needs to be multiple of two. So safer to default to
-	blksize and blkbits set in superblock so 2**blkbits and blksize
-	will match rather than setting to:
-	(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
-
-	/* Linux can not store file creation time so ignore it */
-	if (pfindData->LastAccessTime)
-		inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime);
-	else /* do not need to use current_fs_time - time not stored */
-		inode->i_atime = CURRENT_TIME;
-	inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime);
-	inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime);
-	cFYI(DBG2, ("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;
-	}
-
-	/* get default inode mode */
-	if (attr & ATTR_DIRECTORY)
-		default_mode = cifs_sb->mnt_dir_mode;
-	else
-		default_mode = cifs_sb->mnt_file_mode;
-
-	/* set permission bits */
-	if (atomic_read(&cifsInfo->inUse) == 0 ||
-	    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
-		inode->i_mode = default_mode;
-	else {
-		/* just reenable write bits if !ATTR_READONLY */
-		if ((inode->i_mode & S_IWUGO) == 0 &&
-		    (attr & ATTR_READONLY) == 0)
-			inode->i_mode |= (S_IWUGO & default_mode);
-
-		inode->i_mode &= ~S_IFMT;
-	}
-	/* clear write bits if ATTR_READONLY is set */
-	if (attr & ATTR_READONLY)
-		inode->i_mode &= ~S_IWUGO;
-
-	/* set inode type */
-	if ((attr & ATTR_SYSTEM) &&
-	    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
-		/* no need to fix endianness on 0 */
-		if (pfindData->EndOfFile == 0)
-			inode->i_mode |= S_IFIFO;
-		else if (decode_sfu_inode(inode,
-				le64_to_cpu(pfindData->EndOfFile),
-				full_path, cifs_sb, xid))
-			cFYI(1, ("unknown SFU file type\n"));
 	} else {
-		if (attr & ATTR_DIRECTORY)
-			inode->i_mode |= S_IFDIR;
-		else
-			inode->i_mode |= S_IFREG;
+		fattr->cf_uniqueid = CIFS_I(*pinode)->uniqueid;
 	}
 
-	cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile);
-	spin_lock(&inode->i_lock);
-	if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) {
-		/* can not safely shrink the file size here if the
-		   client is writing to it due to potential races */
-		i_size_write(inode, cifsInfo->server_eof);
-
-		/* 512 bytes (2**9) is the fake blocksize that must be
-		   used for this calculation */
-		inode->i_blocks = (512 - 1 + le64_to_cpu(
-				   pfindData->AllocationSize)) >> 9;
+	/* query for SFU type info if supported and needed */
+	if (fattr->cf_cifsattrs & ATTR_SYSTEM &&
+	    cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+		tmprc = cifs_sfu_type(fattr, full_path, cifs_sb, xid);
+		if (tmprc)
+			cFYI(1, ("cifs_sfu_type failed: %d", tmprc));
 	}
-	spin_unlock(&inode->i_lock);
 
-	inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
-
-	/* BB fill in uid and gid here? with help from winbind?
-	   or retrieve from NTFS stream extended attribute */
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 	/* fill in 0777 bits from ACL */
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
 		cFYI(1, ("Getting mode bits from ACL"));
-		acl_to_uid_mode(inode, full_path, pfid);
+		cifs_acl_to_fattr(fattr, *pinode, full_path, pfid);
 	}
 #endif
-	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
-		/* fill in remaining high mode bits e.g. SUID, VTX */
-		get_sfu_mode(inode, full_path, cifs_sb, xid);
-	} else if (atomic_read(&cifsInfo->inUse) == 0) {
-		inode->i_uid = cifs_sb->mnt_uid;
-		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);
-	}
-
-	cifs_set_ops(inode, is_dfs_referral);
-
 
+	/* fill in remaining high mode bits e.g. SUID, VTX */
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
+		cifs_sfu_mode(fattr, full_path, cifs_sb, xid);
 
+	if (!*pinode) {
+		*pinode = cifs_iget(sb, fattr);
+		if (!*pinode)
+			rc = -ENOMEM;
+	} else {
+		cifs_fattr_to_inode(*pinode, fattr);
+	}
 
 cgii_exit:
 	kfree(buf);
+	kfree(fattr);
 	return rc;
 }
 
@@ -772,21 +737,14 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
 		return ERR_PTR(-ENOMEM);
 
 	xid = GetXid();
-	if (cifs_sb->tcon->unix_ext) {
+	if (cifs_sb->tcon->unix_ext)
 		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
-		if (!inode)
-			return ERR_PTR(-ENOMEM);
-	} else {
-		inode = iget_locked(sb, ino);
-		if (!inode)
-			return ERR_PTR(-ENOMEM);
-		if (!(inode->i_state & I_NEW))
-			return inode;
-
-		rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
+	else
+		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
 						xid, NULL);
-		unlock_new_inode(inode);
-	}
+
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
 
 	if (rc && cifs_sb->tcon->ipc) {
 		cFYI(1, ("ipc connection - fake read inode"));
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 09/13] cifs: convert non-posix readdir codepath to use cifs_iget
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (7 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 08/13] cifs: convert cifs_get_inode_info " Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:24 ` [PATCH 10/13] cifs: remove cifs_new_inode Jeff Layton
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsglob.h |    1 +
 fs/cifs/inode.c    |   10 +-
 fs/cifs/readdir.c  |  350 +++++++++++++---------------------------------------
 3 files changed, 96 insertions(+), 265 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a5e55e7..f379e83 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -481,6 +481,7 @@ struct dfs_info3_param {
 
 #define CIFS_FATTR_DFS_REFERRAL		0x1
 #define CIFS_FATTR_DELETE_PENDING	0x2
+#define CIFS_FATTR_NEED_REVAL		0x4
 
 struct cifs_fattr {
 	u32		cf_flags;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 2b1c0cf..f8c48d8 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -83,7 +83,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 {
 	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	unsigned long now = jiffies;
+	unsigned long oldtime = cifs_i->time;
 
 	inode->i_atime = fattr->cf_atime;
 	inode->i_mtime = fattr->cf_mtime;
@@ -101,9 +101,13 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 	cifs_i->cifsAttrs = fattr->cf_cifsattrs;
 	cifs_i->uniqueid = fattr->cf_uniqueid;
 
+	if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
+		cifs_i->time = 0;
+	else
+		cifs_i->time = jiffies;
+
 	cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
-		 cifs_i->time, now));
-	cifs_i->time = now;
+		 oldtime, cifs_i->time));
 
 	/*
 	 * Can't safely change the file size here if the client is writing to
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index c86b293..fc1a19d 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -112,239 +112,85 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
 	return dentry;
 }
 
-/* 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 */
-static int
-construct_dentry(struct qstr *qstring, struct file *file,
-		 struct inode **ptmp_inode, struct dentry **pnew_dentry,
-		 __u64 *inum)
+static void
+cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
 {
-	struct dentry *tmp_dentry = NULL;
-	struct super_block *sb = file->f_path.dentry->d_sb;
-	int rc = 0;
 
-	cFYI(1, ("For %s", qstring->name));
-
-	tmp_dentry = d_lookup(file->f_path.dentry, qstring);
-	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",
-			 tmp_dentry->d_inode));
-		*ptmp_inode = tmp_dentry->d_inode;
-		if (*ptmp_inode == NULL) {
-			*ptmp_inode = cifs_new_inode(sb, inum);
-			if (*ptmp_inode == NULL)
-				return rc;
-			rc = 1;
-		}
+	fattr->cf_uid = cifs_sb->mnt_uid;
+	fattr->cf_gid = cifs_sb->mnt_gid;
+
+	if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
+		fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
+		fattr->cf_dtype = DT_DIR;
 	} else {
-		tmp_dentry = d_alloc(file->f_path.dentry, qstring);
-		if (tmp_dentry == NULL) {
-			cERROR(1, ("Failed allocating dentry"));
-			*ptmp_inode = NULL;
-			return rc;
-		}
+		fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
+		fattr->cf_dtype = DT_REG;
+	}
 
-		if (CIFS_SB(sb)->tcon->nocase)
-			tmp_dentry->d_op = &cifs_ci_dentry_ops;
-		else
-			tmp_dentry->d_op = &cifs_dentry_ops;
+	if (fattr->cf_cifsattrs & ATTR_READONLY)
+		fattr->cf_mode &= ~S_IWUGO;
 
-		*ptmp_inode = cifs_new_inode(sb, inum);
-		if (*ptmp_inode == NULL)
-			return rc;
-		rc = 2;
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
+	    fattr->cf_cifsattrs & ATTR_SYSTEM) {
+		if (fattr->cf_eof == 0)  {
+			fattr->cf_mode &= ~S_IFMT;
+			fattr->cf_mode |= S_IFIFO;
+			fattr->cf_dtype = DT_FIFO;
+		} else {
+			/*
+			 * trying to get the type and mode via SFU can be slow,
+			 * so just call those regular files for now, and mark
+			 * for reval
+			 */
+			fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
+		}
 	}
-
-	tmp_dentry->d_time = jiffies;
-	*pnew_dentry = tmp_dentry;
-	return rc;
 }
-
-static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
-			  char *buf, unsigned int *pobject_type, int isNewInode)
+		
+static struct cifs_fattr *
+cifs_dir_info_to_fattr(FILE_DIRECTORY_INFO *info, struct cifs_sb_info *cifs_sb)
 {
-	loff_t local_size;
-	struct timespec local_mtime;
-
-	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
-	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
-	__u32 attr;
-	__u64 allocation_size;
-	__u64 end_of_file;
-	umode_t default_mode;
-
-	/* save mtime and size */
-	local_mtime = tmp_inode->i_mtime;
-	local_size  = tmp_inode->i_size;
-
-	if (new_buf_type) {
-		FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
-
-		attr = le32_to_cpu(pfindData->ExtFileAttributes);
-		allocation_size = le64_to_cpu(pfindData->AllocationSize);
-		end_of_file = le64_to_cpu(pfindData->EndOfFile);
-		tmp_inode->i_atime =
-			cifs_NTtimeToUnix(pfindData->LastAccessTime);
-		tmp_inode->i_mtime =
-			cifs_NTtimeToUnix(pfindData->LastWriteTime);
-		tmp_inode->i_ctime =
-			cifs_NTtimeToUnix(pfindData->ChangeTime);
-	} else { /* legacy, OS2 and DOS style */
-		int offset = cifs_sb->tcon->ses->server->timeAdj;
-		FIND_FILE_STANDARD_INFO *pfindData =
-			(FIND_FILE_STANDARD_INFO *)buf;
-
-		tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
-						    pfindData->LastWriteTime,
-						    offset);
-		tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
-						    pfindData->LastAccessTime,
-						    offset);
-		tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
-						    pfindData->LastWriteTime,
-						    offset);
-		attr = le16_to_cpu(pfindData->Attributes);
-		allocation_size = le32_to_cpu(pfindData->AllocationSize);
-		end_of_file = le32_to_cpu(pfindData->DataSize);
-	}
+	struct cifs_fattr *fattr = kzalloc(sizeof(*fattr), GFP_KERNEL);
 
-	/* Linux can not store file creation time unfortunately so ignore it */
+	if (!fattr)
+		return NULL;
 
-	cifsInfo->cifsAttrs = attr;
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-		/* get more accurate mode via ACL - so force inode refresh */
-		cifsInfo->time = 0;
-	} else
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
-		cifsInfo->time = jiffies;
-
-	/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
-	/* 2767 perms - indicate mandatory locking */
-		/* BB fill in uid and gid here? with help from winbind?
-		   or retrieve from NTFS stream extended attribute */
-	if (atomic_read(&cifsInfo->inUse) == 0) {
-		tmp_inode->i_uid = cifs_sb->mnt_uid;
-		tmp_inode->i_gid = cifs_sb->mnt_gid;
-	}
+	fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
+	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+	fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
+	fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+	fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
+	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
 
-	if (attr & ATTR_DIRECTORY)
-		default_mode = cifs_sb->mnt_dir_mode;
-	else
-		default_mode = cifs_sb->mnt_file_mode;
-
-	/* set initial permissions */
-	if ((atomic_read(&cifsInfo->inUse) == 0) ||
-	    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
-		tmp_inode->i_mode = default_mode;
-	else {
-		/* just reenable write bits if !ATTR_READONLY */
-		if ((tmp_inode->i_mode & S_IWUGO) == 0 &&
-		    (attr & ATTR_READONLY) == 0)
-			tmp_inode->i_mode |= (S_IWUGO & default_mode);
-
-		tmp_inode->i_mode &= ~S_IFMT;
-	}
+	cifs_fill_common_info(fattr, cifs_sb);
 
-	/* clear write bits if ATTR_READONLY is set */
-	if (attr & ATTR_READONLY)
-		tmp_inode->i_mode &= ~S_IWUGO;
+	return fattr;
+}
 
-	/* set inode type */
-	if ((attr & ATTR_SYSTEM) &&
-	    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
-		if (end_of_file == 0)  {
-			tmp_inode->i_mode |= S_IFIFO;
-			*pobject_type = DT_FIFO;
-		} else {
-			/*
-			 * trying to get the type can be slow, so just call
-			 * this a regular file for now, and mark for reval
-			 */
-			tmp_inode->i_mode |= S_IFREG;
-			*pobject_type = DT_REG;
-			cifsInfo->time = 0;
-		}
-	} else {
-		if (attr & ATTR_DIRECTORY) {
-			tmp_inode->i_mode |= S_IFDIR;
-			*pobject_type = DT_DIR;
-		} else {
-			tmp_inode->i_mode |= S_IFREG;
-			*pobject_type = DT_REG;
-		}
-	}
+static struct cifs_fattr *
+cifs_std_info_to_fattr(FIND_FILE_STANDARD_INFO *info,
+		       struct cifs_sb_info *cifs_sb)
+{
+	int offset = cifs_sb->tcon->ses->server->timeAdj;
+	struct cifs_fattr *fattr = kzalloc(sizeof(*fattr), GFP_KERNEL);
 
-	/* can not fill in nlink here as in qpathinfo version and Unx search */
-	if (atomic_read(&cifsInfo->inUse) == 0)
-		atomic_set(&cifsInfo->inUse, 1);
+	if (!fattr)
+		return NULL;
 
-	cifsInfo->server_eof = end_of_file;
-	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
-		client is writing to it due to potential races */
-		i_size_write(tmp_inode, end_of_file);
+	fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
+					    info->LastAccessTime, offset);
+	fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
+					    info->LastWriteTime, offset);
+	fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
+					    info->LastWriteTime, offset);
 
-	/* 512 bytes (2**9) is the fake blocksize that must be used */
-	/* for this calculation, even though the reported blocksize is larger */
-		tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
-	}
-	spin_unlock(&tmp_inode->i_lock);
-
-	if (allocation_size < end_of_file)
-		cFYI(1, ("May be sparse file, allocation less than file size"));
-	cFYI(1, ("File Size %ld and blocks %llu",
-		(unsigned long)tmp_inode->i_size,
-		(unsigned long long)tmp_inode->i_blocks));
-	if (S_ISREG(tmp_inode->i_mode)) {
-		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)
-				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)
-			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 <
-			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 have not started caching readahead file
-				   data yet */
-
-		if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
-			(local_size == tmp_inode->i_size)) {
-			cFYI(1, ("inode exists but unchanged"));
-		} else {
-			/* file may have changed on server */
-			cFYI(1, ("invalidate inode, readdir detected change"));
-			invalidate_remote_inode(tmp_inode);
-		}
-	} else if (S_ISDIR(tmp_inode->i_mode)) {
-		cFYI(1, ("Directory inode"));
-		tmp_inode->i_op = &cifs_dir_inode_ops;
-		tmp_inode->i_fop = &cifs_dir_ops;
-	} else if (S_ISLNK(tmp_inode->i_mode)) {
-		cFYI(1, ("Symbolic Link inode"));
-		tmp_inode->i_op = &cifs_symlink_inode_ops;
-	} else {
-		cFYI(1, ("Init special inode"));
-		init_special_inode(tmp_inode, tmp_inode->i_mode,
-				   tmp_inode->i_rdev);
-	}
+	fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
+	fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
+	fattr->cf_eof = le32_to_cpu(info->DataSize);
+
+	cifs_fill_common_info(fattr, cifs_sb);
+
+	return fattr;
 }
 
 /*
@@ -920,10 +766,9 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
 	int rc = 0;
 	struct qstr qstring;
 	struct cifsFileInfo *pCifsF;
-	unsigned int obj_type;
 	__u64  inum;
+	struct super_block *sb;
 	struct cifs_sb_info *cifs_sb;
-	struct inode *tmp_inode;
 	struct dentry *tmp_dentry;
 	struct cifs_fattr *fattr = NULL;
 
@@ -943,7 +788,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
 	if (rc != 0)
 		return 0;
 
-	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+	sb = file->f_path.dentry->d_sb;
+	cifs_sb = CIFS_SB(sb);
 
 	qstring.name = scratch_buf;
 	rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
@@ -955,56 +801,36 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
 	if (rc)
 		return rc;
 
-	/* only these two infolevels return valid inode numbers */
-	if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
+	if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
 		fattr = cifs_unix_info_to_fattr((FILE_UNIX_INFO *) pfindEntry,
 						cifs_sb);
-		if (!fattr) {
-			rc = -ENOMEM;
-			goto out;
-		}
-
-		tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring,
-						 fattr);
-		if (!tmp_dentry) {
-			rc = -ENOMEM;
-			goto out;
-		}
+	else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
+		fattr = cifs_std_info_to_fattr((FIND_FILE_STANDARD_INFO *)
+						pfindEntry, cifs_sb);
+	else
+		fattr = cifs_dir_info_to_fattr((FILE_DIRECTORY_INFO *)
+						pfindEntry, cifs_sb);
 
-		obj_type = fattr->cf_dtype;
-	} else {
-		if (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)) {
-			rc = -ENOMEM;
-			goto out;
-		}
+	if (!fattr) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
-		/* we pass in rc below, indicating whether it is a new inode,
-		 * so we can figure out whether to invalidate the inode cached
-		 * data if the file has changed
-		 */
-		if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
-			fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc);
-		else
-			fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc);
+	/* 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)
+		fattr->cf_uniqueid = inum;
+	else
+		fattr->cf_uniqueid = iunique(sb, ROOT_I);
 
-		/* new inode - needs to be tied to dentry */
-		if (rc) {
-			d_instantiate(tmp_dentry, tmp_inode);
-			if (rc == 2)
-				d_rehash(tmp_dentry);
-		}
+	tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, fattr);
+	if (!tmp_dentry || !tmp_dentry->d_inode) {
+		rc = -ENOMEM;
+		goto out;
 	}
 
 	rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
-		     tmp_inode->i_ino, obj_type);
+		     tmp_dentry->d_inode->i_ino, fattr->cf_dtype);
 	if (rc) {
 		cFYI(1, ("filldir rc = %d", rc));
 		/* we can not return filldir errors to the caller
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 10/13] cifs: remove cifs_new_inode
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (8 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 09/13] cifs: convert non-posix readdir codepath " Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:24 ` [PATCH 11/13] cifs: make serverino the default when mounting Jeff Layton
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsproto.h |    1 -
 fs/cifs/inode.c     |   43 -------------------------------------------
 2 files changed, 0 insertions(+), 44 deletions(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index d572647..65715e5 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -101,7 +101,6 @@ extern int cifs_posix_open(char *full_path, struct inode **pinode,
 extern struct cifs_fattr *cifs_unix_basic_to_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);
 
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f8c48d8..36b4417 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -248,49 +248,6 @@ cifs_create_fake_fattr(struct super_block *sb)
 	return fattr;
 }
 
-/**
- * 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, __u64 *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 = (unsigned long) *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,
 	const unsigned char *full_path, struct super_block *sb, int xid)
 {
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 11/13] cifs: make serverino the default when mounting
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (9 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 10/13] cifs: remove cifs_new_inode Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:24 ` [PATCH 12/13] cifs: remove cifsInodeInfo->inUse counter Jeff Layton
  2009-05-11 20:24 ` [PATCH 13/13] cifs: remove "hardlink detection" from cifs_rename Jeff Layton
  12 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/connect.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4aa81a5..bd78f18 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -835,6 +835,8 @@ cifs_parse_mount_options(char *options, const char *devname,
 	vol->rw = true;
 	/* default is always to request posix paths. */
 	vol->posix_paths = 1;
+	/* default to using server inode numbers where available */
+	vol->server_ino = 1;
 
 	if (!options)
 		return 1;
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 12/13] cifs: remove cifsInodeInfo->inUse counter
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (10 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 11/13] cifs: make serverino the default when mounting Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  2009-05-11 20:24 ` [PATCH 13/13] cifs: remove "hardlink detection" from cifs_rename Jeff Layton
  12 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

It was purported to be a refcounter of some sort, but was never
used that way. It never served any purpose that wasn't served equally well
by the I_NEW flag.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsfs.c   |    1 -
 fs/cifs/cifsglob.h |    1 -
 2 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 65a651c..58f8fc8 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -303,7 +303,6 @@ cifs_alloc_inode(struct super_block *sb)
 	if (!cifs_inode)
 		return NULL;
 	cifs_inode->cifsAttrs = 0x20;	/* default */
-	atomic_set(&cifs_inode->inUse, 0);
 	cifs_inode->time = 0;
 	cifs_inode->write_behind_rc = 0;
 	/* Until the file is open and we have gotten oplock
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index f379e83..ad8608c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -364,7 +364,6 @@ struct cifsInodeInfo {
 	struct list_head openFileList;
 	int write_behind_rc;
 	__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
-	atomic_t inUse;	 /* num concurrent users (local openers cifs) of file*/
 	unsigned long time;	/* jiffies of last update/check of inode */
 	bool clientCanCacheRead:1;	/* read oplock */
 	bool clientCanCacheAll:1;	/* read and writebehind oplock */
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 13/13] cifs: remove "hardlink detection" from cifs_rename
  2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
                   ` (11 preceding siblings ...)
  2009-05-11 20:24 ` [PATCH 12/13] cifs: remove cifsInodeInfo->inUse counter Jeff Layton
@ 2009-05-11 20:24 ` Jeff Layton
  12 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 20:24 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: linux-fsdevel

Because cifs never handled hardlinks correctly, there was a rather
nasty hack in cifs_rename to try and detect them. It only ever worked
on POSIX mounts anyway. Now that cifs has proper hardlink detection,
that can be removed.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/inode.c |   60 +------------------------------------------------------
 1 files changed, 1 insertions(+), 59 deletions(-)

diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 36b4417..4e1fa77 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1326,29 +1326,11 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
 {
 	char *fromName = NULL;
 	char *toName = NULL;
-	struct cifs_sb_info *cifs_sb_source;
-	struct cifs_sb_info *cifs_sb_target;
-	struct cifsTconInfo *tcon;
-	FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
-	FILE_UNIX_BASIC_INFO *info_buf_target;
 	int xid, rc, tmprc;
 
-	cifs_sb_target = CIFS_SB(target_dir->i_sb);
-	cifs_sb_source = CIFS_SB(source_dir->i_sb);
-	tcon = cifs_sb_source->tcon;
-
 	xid = GetXid();
 
 	/*
-	 * BB: this might be allowed if same server, but different share.
-	 * Consider adding support for this
-	 */
-	if (tcon != cifs_sb_target->tcon) {
-		rc = -EXDEV;
-		goto cifs_rename_exit;
-	}
-
-	/*
 	 * we already have the rename sem so we do not need to
 	 * grab it again here to protect the path integrity
 	 */
@@ -1367,46 +1349,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
 	rc = cifs_do_rename(xid, source_dentry, fromName,
 			    target_dentry, toName);
 
-	if (rc == -EEXIST && tcon->unix_ext) {
-		/*
-		 * Are src and dst hardlinks of same inode? We can
-		 * only tell with unix extensions enabled
-		 */
-		info_buf_source =
-			kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
-					GFP_KERNEL);
-		if (info_buf_source == NULL) {
-			rc = -ENOMEM;
-			goto cifs_rename_exit;
-		}
-
-		info_buf_target = info_buf_source + 1;
-		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
-					info_buf_source,
-					cifs_sb_source->local_nls,
-					cifs_sb_source->mnt_cifs_flags &
-					CIFS_MOUNT_MAP_SPECIAL_CHR);
-		if (tmprc != 0)
-			goto unlink_target;
-
-		tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
-					toName, info_buf_target,
-					cifs_sb_target->local_nls,
-					/* remap based on source sb */
-					cifs_sb_source->mnt_cifs_flags &
-					CIFS_MOUNT_MAP_SPECIAL_CHR);
-
-		if (tmprc == 0 && (info_buf_source->UniqueId ==
-				   info_buf_target->UniqueId)) {
-			/* same file, POSIX says that this is a noop */
-			rc = 0;
-			goto cifs_rename_exit;
-		}
-	} /* else ... BB we could add the same check for Windows by
-		     checking the UniqueId via FILE_INTERNAL_INFO */
-
-unlink_target:
-	/* Try unlinking the target dentry if it's not negative */
+	/* unlink the target, but only if it looks like the file exists */
 	if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
 		tmprc = cifs_unlink(target_dir, target_dentry);
 		if (tmprc)
@@ -1417,7 +1360,6 @@ unlink_target:
 	}
 
 cifs_rename_exit:
-	kfree(info_buf_source);
 	kfree(fromName);
 	kfree(toName);
 	FreeXid(xid);
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/13] cifs: have cifs_NTtimeToUnix take a little-endian arg
  2009-05-11 20:24 ` [PATCH 01/13] cifs: have cifs_NTtimeToUnix take a little-endian arg Jeff Layton
@ 2009-05-11 20:26   ` Christoph Hellwig
  0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-05-11 20:26 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-fsdevel, linux-cifs-client

On Mon, May 11, 2009 at 04:24:20PM -0400, Jeff Layton wrote:
> ...and just have the function call le64_to_cpu.

Looks good.


Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/13] cifs: make cnvrtDosUnixTm take a little-endian args and an offset
  2009-05-11 20:24 ` [PATCH 02/13] cifs: make cnvrtDosUnixTm take a little-endian args and an offset Jeff Layton
@ 2009-05-11 20:27   ` Christoph Hellwig
  0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-05-11 20:27 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-fsdevel, linux-cifs-client

On Mon, May 11, 2009 at 04:24:21PM -0400, Jeff Layton wrote:
> The callers primarily end up converting the args from le anyway. Also,
> most of the callers end up needing to add an offset to the result. The
> exception to these rules is cnvrtDosCifsTm, but there are no callers of
> that function, so we might as well remove it.

Nice cleanup.

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode
  2009-05-11 20:24 ` [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode Jeff Layton
@ 2009-05-11 20:56   ` Christoph Hellwig
  2009-05-11 21:03     ` Jeff Layton
  0 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-05-11 20:56 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-cifs-client, linux-fsdevel

On Mon, May 11, 2009 at 04:24:22PM -0400, Jeff Layton wrote:
> We'll need this later when we restructure cifs_get_inode_info.
> 
> Signed-off-by: Jeff Layton <jlayton@redhat.com>
> ---
>  fs/cifs/cifsacl.c |   25 ++++++-------------------
>  1 files changed, 6 insertions(+), 19 deletions(-)
> 
>  static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
> -				       const char *path, const __u16 *pfid)
> +				      const char *path, const __u16 *pfid)
>  {
>  	struct cifsFileInfo *open_file = NULL;
> -	bool unlock_file = false;
>  	int xid;
>  	int rc = -EIO;
>  	__u16 fid;
> -	struct super_block *sb;
> -	struct cifs_sb_info *cifs_sb;
>  	struct cifs_ntsd *pntsd = NULL;
> +	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);

This isn't going to work with a NULL inode.

But this whole set_cifs_acl function is a real mess anyway and needs
some splitting up.  What about the untested patch below?


Index: linux-2.6/fs/cifs/cifsacl.c
===================================================================
--- linux-2.6.orig/fs/cifs/cifsacl.c	2009-05-11 22:35:29.841784452 +0200
+++ linux-2.6/fs/cifs/cifsacl.c	2009-05-11 22:55:19.465660251 +0200
@@ -552,67 +552,65 @@ static int build_sec_desc(struct cifs_nt
 	return rc;
 }
 
-
-/* Retrieve an ACL from the server */
-static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
-				       const char *path, const __u16 *pfid)
+static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
+		__u16 fid, u32 *pacllen)
 {
-	struct cifsFileInfo *open_file = NULL;
-	bool unlock_file = false;
-	int xid;
-	int rc = -EIO;
-	__u16 fid;
-	struct super_block *sb;
-	struct cifs_sb_info *cifs_sb;
 	struct cifs_ntsd *pntsd = NULL;
+	int xid, rc;
 
-	cFYI(1, ("get mode from ACL for %s", path));
+	xid = GetXid();
+	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+	FreeXid(xid);
 
-	if (inode == NULL)
-		return NULL;
 
-	xid = GetXid();
-	if (pfid == NULL)
-		open_file = find_readable_file(CIFS_I(inode));
-	else
-		fid = *pfid;
+	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
+	return pntsd;
+}
 
-	sb = inode->i_sb;
-	if (sb == NULL) {
-		FreeXid(xid);
-		return NULL;
-	}
-	cifs_sb = CIFS_SB(sb);
+static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
+		const char *path, u32 *pacllen)
+{
+	struct cifs_ntsd *pntsd = NULL;
+	int oplock = 0;
+	int xid, rc;
+	__u16 fid;
 
-	if (open_file) {
-		unlock_file = true;
-		fid = open_file->netfid;
-	} else if (pfid == NULL) {
-		int oplock = 0;
-		/* open file */
-		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
-				READ_CONTROL, 0, &fid, &oplock, NULL,
-				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
-					CIFS_MOUNT_MAP_SPECIAL_CHR);
-		if (rc != 0) {
-			cERROR(1, ("Unable to open file to get ACL"));
-			FreeXid(xid);
-			return NULL;
-		}
+	xid = GetXid();
+
+	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
+			 &fid, &oplock, NULL, cifs_sb->local_nls,
+			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+	if (rc) {
+		cERROR(1, ("Unable to open file to get ACL"));
+		goto out;
 	}
 
 	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
 	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
-	if (unlock_file == true) /* find_readable_file increments ref count */
-		atomic_dec(&open_file->wrtPending);
-	else if (pfid == NULL) /* if opened above we have to close the handle */
-		CIFSSMBClose(xid, cifs_sb->tcon, fid);
-	/* else handle was passed in by caller */
 
+	CIFSSMBClose(xid, cifs_sb->tcon, fid);
+ out:
 	FreeXid(xid);
 	return pntsd;
 }
 
+/* Retrieve an ACL from the server */
+static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
+				       const char *path)
+{
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct cifs_ntsd *pntsd = NULL;
+	struct cifsFileInfo *open_file;
+
+	open_file = find_readable_file(CIFS_I(inode));
+	if (!open_file)
+		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
+
+	pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
+	atomic_dec(&open_file->wrtPending);
+	return pntsd;
+}
+
 /* Set an ACL on the server */
 static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
 				struct inode *inode, const char *path)
@@ -675,7 +673,13 @@ void acl_to_uid_mode(struct inode *inode
 	int rc = 0;
 
 	cFYI(DBG2, ("converting ACL to mode for %s", path));
-	pntsd = get_cifs_acl(&acllen, inode, path, pfid);
+
+	if (pfid) {
+		pntsd = get_cifs_acl_by_fid(CIFS_SB(inode->i_sb), *pfid,
+					    &acllen);
+	} else {
+		pntsd = get_cifs_acl(&acllen, inode, path);
+	}
 
 	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
 	if (pntsd)
@@ -698,7 +702,7 @@ int mode_to_acl(struct inode *inode, con
 	cFYI(DBG2, ("set ACL from mode for %s", path));
 
 	/* Get the security descriptor */
-	pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
+	pntsd = get_cifs_acl(&secdesclen, inode, path);
 
 	/* Add three ACEs for owner, group, everyone getting rid of
 	   other ACEs as chmod disables ACEs and set the security descriptor */

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 05/13] cifs: add new cifs_fattr struct for holding cifs inode attributes in common way
  2009-05-11 20:24 ` [PATCH 05/13] cifs: add new cifs_fattr struct for holding cifs inode attributes in common way Jeff Layton
@ 2009-05-11 21:01   ` Christoph Hellwig
  0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-05-11 21:01 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-cifs-client, linux-fsdevel

On Mon, May 11, 2009 at 04:24:24PM -0400, Jeff Layton wrote:
> 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.

Looks good, but should probably be merged into the next patch so that
we introduce a user together with the new structure.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode
  2009-05-11 20:56   ` Christoph Hellwig
@ 2009-05-11 21:03     ` Jeff Layton
  2009-05-13  9:09       ` Christoph Hellwig
  0 siblings, 1 reply; 22+ messages in thread
From: Jeff Layton @ 2009-05-11 21:03 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-cifs-client, linux-fsdevel

On Mon, 11 May 2009 16:56:21 -0400
Christoph Hellwig <hch@infradead.org> wrote:

> On Mon, May 11, 2009 at 04:24:22PM -0400, Jeff Layton wrote:
> > We'll need this later when we restructure cifs_get_inode_info.
> > 
> > Signed-off-by: Jeff Layton <jlayton@redhat.com>
> > ---
> >  fs/cifs/cifsacl.c |   25 ++++++-------------------
> >  1 files changed, 6 insertions(+), 19 deletions(-)
> > 
> >  static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
> > -				       const char *path, const __u16 *pfid)
> > +				      const char *path, const __u16 *pfid)
> >  {
> >  	struct cifsFileInfo *open_file = NULL;
> > -	bool unlock_file = false;
> >  	int xid;
> >  	int rc = -EIO;
> >  	__u16 fid;
> > -	struct super_block *sb;
> > -	struct cifs_sb_info *cifs_sb;
> >  	struct cifs_ntsd *pntsd = NULL;
> > +	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
> 
> This isn't going to work with a NULL inode.
> 

Oops. Good catch!

> But this whole set_cifs_acl function is a real mess anyway and needs
> some splitting up.  What about the untested patch below?
> 

Looks good. I'll plan to incorporate this or something close to it on
the next respin.

Thanks for the review so far.

> 
> Index: linux-2.6/fs/cifs/cifsacl.c
> ===================================================================
> --- linux-2.6.orig/fs/cifs/cifsacl.c	2009-05-11 22:35:29.841784452 +0200
> +++ linux-2.6/fs/cifs/cifsacl.c	2009-05-11 22:55:19.465660251 +0200
> @@ -552,67 +552,65 @@ static int build_sec_desc(struct cifs_nt
>  	return rc;
>  }
>  
> -
> -/* Retrieve an ACL from the server */
> -static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
> -				       const char *path, const __u16 *pfid)
> +static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
> +		__u16 fid, u32 *pacllen)
>  {
> -	struct cifsFileInfo *open_file = NULL;
> -	bool unlock_file = false;
> -	int xid;
> -	int rc = -EIO;
> -	__u16 fid;
> -	struct super_block *sb;
> -	struct cifs_sb_info *cifs_sb;
>  	struct cifs_ntsd *pntsd = NULL;
> +	int xid, rc;
>  
> -	cFYI(1, ("get mode from ACL for %s", path));
> +	xid = GetXid();
> +	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
> +	FreeXid(xid);
>  
> -	if (inode == NULL)
> -		return NULL;
>  
> -	xid = GetXid();
> -	if (pfid == NULL)
> -		open_file = find_readable_file(CIFS_I(inode));
> -	else
> -		fid = *pfid;
> +	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
> +	return pntsd;
> +}
>  
> -	sb = inode->i_sb;
> -	if (sb == NULL) {
> -		FreeXid(xid);
> -		return NULL;
> -	}
> -	cifs_sb = CIFS_SB(sb);
> +static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
> +		const char *path, u32 *pacllen)
> +{
> +	struct cifs_ntsd *pntsd = NULL;
> +	int oplock = 0;
> +	int xid, rc;
> +	__u16 fid;
>  
> -	if (open_file) {
> -		unlock_file = true;
> -		fid = open_file->netfid;
> -	} else if (pfid == NULL) {
> -		int oplock = 0;
> -		/* open file */
> -		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
> -				READ_CONTROL, 0, &fid, &oplock, NULL,
> -				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
> -					CIFS_MOUNT_MAP_SPECIAL_CHR);
> -		if (rc != 0) {
> -			cERROR(1, ("Unable to open file to get ACL"));
> -			FreeXid(xid);
> -			return NULL;
> -		}
> +	xid = GetXid();
> +
> +	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
> +			 &fid, &oplock, NULL, cifs_sb->local_nls,
> +			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
> +	if (rc) {
> +		cERROR(1, ("Unable to open file to get ACL"));
> +		goto out;
>  	}
>  
>  	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
>  	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
> -	if (unlock_file == true) /* find_readable_file increments ref count */
> -		atomic_dec(&open_file->wrtPending);
> -	else if (pfid == NULL) /* if opened above we have to close the handle */
> -		CIFSSMBClose(xid, cifs_sb->tcon, fid);
> -	/* else handle was passed in by caller */
>  
> +	CIFSSMBClose(xid, cifs_sb->tcon, fid);
> + out:
>  	FreeXid(xid);
>  	return pntsd;
>  }
>  
> +/* Retrieve an ACL from the server */
> +static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
> +				       const char *path)
> +{
> +	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
> +	struct cifs_ntsd *pntsd = NULL;
> +	struct cifsFileInfo *open_file;
> +
> +	open_file = find_readable_file(CIFS_I(inode));
> +	if (!open_file)
> +		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
> +
> +	pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
> +	atomic_dec(&open_file->wrtPending);
> +	return pntsd;
> +}
> +
>  /* Set an ACL on the server */
>  static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
>  				struct inode *inode, const char *path)
> @@ -675,7 +673,13 @@ void acl_to_uid_mode(struct inode *inode
>  	int rc = 0;
>  
>  	cFYI(DBG2, ("converting ACL to mode for %s", path));
> -	pntsd = get_cifs_acl(&acllen, inode, path, pfid);
> +
> +	if (pfid) {
> +		pntsd = get_cifs_acl_by_fid(CIFS_SB(inode->i_sb), *pfid,
> +					    &acllen);
> +	} else {
> +		pntsd = get_cifs_acl(&acllen, inode, path);
> +	}
>  
>  	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
>  	if (pntsd)
> @@ -698,7 +702,7 @@ int mode_to_acl(struct inode *inode, con
>  	cFYI(DBG2, ("set ACL from mode for %s", path));
>  
>  	/* Get the security descriptor */
> -	pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
> +	pntsd = get_cifs_acl(&secdesclen, inode, path);
>  
>  	/* Add three ACEs for owner, group, everyone getting rid of
>  	   other ACEs as chmod disables ACEs and set the security descriptor */



-- 
Jeff Layton <jlayton@redhat.com>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 06/13] cifs: add new cifs_iget function and convert unix codepath to use it
  2009-05-11 20:24 ` [PATCH 06/13] cifs: add new cifs_iget function and convert unix codepath to use it Jeff Layton
@ 2009-05-11 21:06   ` Christoph Hellwig
  0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-05-11 21:06 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-cifs-client, linux-fsdevel

On Mon, May 11, 2009 at 04:24:25PM -0400, Jeff Layton wrote:
> 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.
> 
> With this, we should then have proper hardlink detection and can
> eventually get rid of some nasty CIFS-specific hacks for handing them.
> 
> Fixing the unix readdir codepath will be done in a later patch.
> 
> Signed-off-by: Jeff Layton <jlayton@redhat.com>

> +	fattr = cifs_unix_basic_to_fattr(presp_data, cifs_sb);
> +	if (!fattr) {
> +		rc = -ENOMEM;
> +		goto posix_open_ret;
> +	}

The cifs_fattr is probably small enough to be stored on-stack in
many places.  And a calling convention where allocations if needed
are done by the caller and cifs_unix_basic_to_fattr just fills the
buffer is probably nicer either way.

>  /*
> + * Allocate a cifs_fattr struct and fill it with fake inode info.
> + *
> + * Needed to setup cifs_fattr data for the directory which is the
> + * junction to the new submount (ie to setup the fake directory
> + * which represents a DFS referral).
> + *
> + * Returns pointer to new cifs_fattr or NULL on error.
>   */

> +static struct cifs_fattr *
> +cifs_create_fake_fattr(struct super_block *sb)

Same comment about caling conventions applies here, too.

Also wou;dn't something like cifs_create_dfsmount_fattr be a better
name?


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode
  2009-05-11 21:03     ` Jeff Layton
@ 2009-05-13  9:09       ` Christoph Hellwig
  2009-05-13 11:02         ` Jeff Layton
  0 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-05-13  9:09 UTC (permalink / raw)
  To: Jeff Layton; +Cc: Christoph Hellwig, linux-cifs-client, linux-fsdevel

On Mon, May 11, 2009 at 05:03:48PM -0400, Jeff Layton wrote:
> Looks good. I'll plan to incorporate this or something close to it on
> the next respin.

Here's a similar one for set_cifs_acl:


Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: linux-2.6/fs/cifs/cifsacl.c
===================================================================
--- linux-2.6.orig/fs/cifs/cifsacl.c	2009-05-13 10:58:01.838660889 +0200
+++ linux-2.6/fs/cifs/cifsacl.c	2009-05-13 11:08:42.006785420 +0200
@@ -611,57 +611,61 @@ static struct cifs_ntsd *get_cifs_acl(u3
 	return pntsd;
 }
 
-/* Set an ACL on the server */
-static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
-				struct inode *inode, const char *path)
+static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
+		struct cifs_ntsd *pnntsd, u32 acllen)
 {
-	struct cifsFileInfo *open_file;
-	bool unlock_file = false;
-	int xid;
-	int rc = -EIO;
-	__u16 fid;
-	struct super_block *sb;
-	struct cifs_sb_info *cifs_sb;
+	int xid, rc;
 
-	cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
+	xid = GetXid();
+	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
+	FreeXid(xid);
 
-	if (!inode)
-		return rc;
+	cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
+	return rc;
+}
 
-	sb = inode->i_sb;
-	if (sb == NULL)
-		return rc;
+static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
+		struct cifs_ntsd *pnntsd, u32 acllen)
+{
+	int oplock = 0;
+	int xid, rc;
+	__u16 fid;
 
-	cifs_sb = CIFS_SB(sb);
 	xid = GetXid();
 
-	open_file = find_readable_file(CIFS_I(inode));
-	if (open_file) {
-		unlock_file = true;
-		fid = open_file->netfid;
-	} else {
-		int oplock = 0;
-		/* open file */
-		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
-				WRITE_DAC, 0, &fid, &oplock, NULL,
-				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
-					CIFS_MOUNT_MAP_SPECIAL_CHR);
-		if (rc != 0) {
-			cERROR(1, ("Unable to open file to set ACL"));
-			FreeXid(xid);
-			return rc;
-		}
+	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
+			 &fid, &oplock, NULL, cifs_sb->local_nls,
+			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+	if (rc) {
+		cERROR(1, ("Unable to open file to set ACL"));
+		goto out;
 	}
 
 	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
 	cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
-	if (unlock_file)
-		atomic_dec(&open_file->wrtPending);
-	else
-		CIFSSMBClose(xid, cifs_sb->tcon, fid);
 
+	CIFSSMBClose(xid, cifs_sb->tcon, fid);
+ out:
 	FreeXid(xid);
+	return rc;
+}
+
+/* Set an ACL on the server */
+static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
+				struct inode *inode, const char *path)
+{
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct cifsFileInfo *open_file;
+	int rc;
+
+	cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
+
+	open_file = find_readable_file(CIFS_I(inode));
+	if (!open_file)
+		return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
 
+	rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
+	atomic_dec(&open_file->wrtPending);
 	return rc;
 }
 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode
  2009-05-13  9:09       ` Christoph Hellwig
@ 2009-05-13 11:02         ` Jeff Layton
  0 siblings, 0 replies; 22+ messages in thread
From: Jeff Layton @ 2009-05-13 11:02 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-cifs-client, linux-fsdevel

On Wed, 13 May 2009 05:09:57 -0400
Christoph Hellwig <hch@infradead.org> wrote:

> On Mon, May 11, 2009 at 05:03:48PM -0400, Jeff Layton wrote:
> > Looks good. I'll plan to incorporate this or something close to it on
> > the next respin.
> 
> Here's a similar one for set_cifs_acl:
> 
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> 

Thanks, looks reasonable. I ended up playing whack-a-mole on another
problem yesterday and didn't get a chance to work on this. I'm about
halfway through respinning these patches to incorporate your comments.

The catch is that we really do want to be able to call get_cifs_acl (or
some variant) w/o a valid inode. What this patchset does is try to
gather up all of the inode info before calling iget5_locked, so it's
quite possible that there won't be an inode to
pass in when we need to fetch the ACL. So, your patch for get_cifs_acl
is a good start, but it'll take a little bit more reorg to get it to
what I need it to do. No biggie though, I'll get something together for
it...


> Index: linux-2.6/fs/cifs/cifsacl.c
> ===================================================================
> --- linux-2.6.orig/fs/cifs/cifsacl.c	2009-05-13 10:58:01.838660889 +0200
> +++ linux-2.6/fs/cifs/cifsacl.c	2009-05-13 11:08:42.006785420 +0200
> @@ -611,57 +611,61 @@ static struct cifs_ntsd *get_cifs_acl(u3
>  	return pntsd;
>  }
>  
> -/* Set an ACL on the server */
> -static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
> -				struct inode *inode, const char *path)
> +static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
> +		struct cifs_ntsd *pnntsd, u32 acllen)
>  {
> -	struct cifsFileInfo *open_file;
> -	bool unlock_file = false;
> -	int xid;
> -	int rc = -EIO;
> -	__u16 fid;
> -	struct super_block *sb;
> -	struct cifs_sb_info *cifs_sb;
> +	int xid, rc;
>  
> -	cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
> +	xid = GetXid();
> +	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
> +	FreeXid(xid);
>  
> -	if (!inode)
> -		return rc;
> +	cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
> +	return rc;
> +}
>  
> -	sb = inode->i_sb;
> -	if (sb == NULL)
> -		return rc;
> +static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
> +		struct cifs_ntsd *pnntsd, u32 acllen)
> +{
> +	int oplock = 0;
> +	int xid, rc;
> +	__u16 fid;
>  
> -	cifs_sb = CIFS_SB(sb);
>  	xid = GetXid();
>  
> -	open_file = find_readable_file(CIFS_I(inode));
> -	if (open_file) {
> -		unlock_file = true;
> -		fid = open_file->netfid;
> -	} else {
> -		int oplock = 0;
> -		/* open file */
> -		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
> -				WRITE_DAC, 0, &fid, &oplock, NULL,
> -				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
> -					CIFS_MOUNT_MAP_SPECIAL_CHR);
> -		if (rc != 0) {
> -			cERROR(1, ("Unable to open file to set ACL"));
> -			FreeXid(xid);
> -			return rc;
> -		}
> +	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
> +			 &fid, &oplock, NULL, cifs_sb->local_nls,
> +			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
> +	if (rc) {
> +		cERROR(1, ("Unable to open file to set ACL"));
> +		goto out;
>  	}
>  
>  	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
>  	cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
> -	if (unlock_file)
> -		atomic_dec(&open_file->wrtPending);
> -	else
> -		CIFSSMBClose(xid, cifs_sb->tcon, fid);
>  
> +	CIFSSMBClose(xid, cifs_sb->tcon, fid);
> + out:
>  	FreeXid(xid);
> +	return rc;
> +}
> +
> +/* Set an ACL on the server */
> +static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
> +				struct inode *inode, const char *path)
> +{
> +	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
> +	struct cifsFileInfo *open_file;
> +	int rc;
> +
> +	cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
> +
> +	open_file = find_readable_file(CIFS_I(inode));
> +	if (!open_file)
> +		return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
>  
> +	rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
> +	atomic_dec(&open_file->wrtPending);
>  	return rc;
>  }
>  


-- 
Jeff Layton <jlayton@redhat.com>

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2009-05-13 11:02 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-11 20:24 [PATCH 00/13] cifs: implement proper hardlink detection Jeff Layton
2009-05-11 20:24 ` [PATCH 01/13] cifs: have cifs_NTtimeToUnix take a little-endian arg Jeff Layton
2009-05-11 20:26   ` Christoph Hellwig
2009-05-11 20:24 ` [PATCH 02/13] cifs: make cnvrtDosUnixTm take a little-endian args and an offset Jeff Layton
2009-05-11 20:27   ` Christoph Hellwig
2009-05-11 20:24 ` [PATCH 03/13] cifs: allow get_cifs_acl to be called without an inode Jeff Layton
2009-05-11 20:56   ` Christoph Hellwig
2009-05-11 21:03     ` Jeff Layton
2009-05-13  9:09       ` Christoph Hellwig
2009-05-13 11:02         ` Jeff Layton
2009-05-11 20:24 ` [PATCH 04/13] cifs: rename cifs_iget to cifs_root_iget Jeff Layton
2009-05-11 20:24 ` [PATCH 05/13] cifs: add new cifs_fattr struct for holding cifs inode attributes in common way Jeff Layton
2009-05-11 21:01   ` Christoph Hellwig
2009-05-11 20:24 ` [PATCH 06/13] cifs: add new cifs_iget function and convert unix codepath to use it Jeff Layton
2009-05-11 21:06   ` Christoph Hellwig
2009-05-11 20:24 ` [PATCH 07/13] cifs: convert posix readdir codepath to use cifs_iget Jeff Layton
2009-05-11 20:24 ` [PATCH 08/13] cifs: convert cifs_get_inode_info " Jeff Layton
2009-05-11 20:24 ` [PATCH 09/13] cifs: convert non-posix readdir codepath " Jeff Layton
2009-05-11 20:24 ` [PATCH 10/13] cifs: remove cifs_new_inode Jeff Layton
2009-05-11 20:24 ` [PATCH 11/13] cifs: make serverino the default when mounting Jeff Layton
2009-05-11 20:24 ` [PATCH 12/13] cifs: remove cifsInodeInfo->inUse counter Jeff Layton
2009-05-11 20:24 ` [PATCH 13/13] cifs: remove "hardlink detection" from cifs_rename Jeff Layton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.