Re: [PATCH] cifs: Add support of Alternate Data Streams

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 10 Sep 2012 07:56:36 -0500
Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> wrote:

> On Mon, Sep 10, 2012 at 7:23 AM, Jeff Layton <jlayton@xxxxxxxxx> wrote:
> 
> > On Sun, 9 Sep 2012 19:31:16 -0500
> > Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> wrote:
> >
> > > i
> > >
> > > On Wed, Sep 5, 2012 at 9:11 AM, Jeff Layton <jlayton@xxxxxxxxx> wrote:
> > >
> > > > On Mon,  3 Sep 2012 18:06:06 -0500
> > > > shirishpargaonkar@xxxxxxxxx wrote:
> > > >
> > > > > From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
> > > > >
> > > > >
> > > > > Add support of Alternate Data Streams (ads).
> > > > > For the support, we need to add additional (desired) access flags
> > > > > to the generic ones that cifs client does currently.
> > > > > The ads files have a : in the name, so that is used to differentiate
> > > > > and add additional desired access.
> > > > > One operations that does not work is Rename (0x7).
> > > > >
> > > > >
> > > > > Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
> > > > > ---
> > > > >  fs/cifs/dir.c   |   12 ++++++++++--
> > > > >  fs/cifs/file.c  |   45 ++++++++++++++++++++++++++++++++++-----------
> > > > >  fs/cifs/inode.c |   14 ++++++++++++++
> > > > >  3 files changed, 58 insertions(+), 13 deletions(-)
> > > > >
> > > > > diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> > > > > index cbe709a..8f8d546 100644
> > > > > --- a/fs/cifs/dir.c
> > > > > +++ b/fs/cifs/dir.c
> > > > > @@ -245,10 +245,18 @@ cifs_do_create(struct inode *inode, struct
> > dentry
> > > > *direntry, unsigned int xid,
> > > > >       }
> > > > >
> > > > >       desiredAccess = 0;
> > > > > -     if (OPEN_FMODE(oflags) & FMODE_READ)
> > > > > +     if (OPEN_FMODE(oflags) & FMODE_READ) {
> > > > >               desiredAccess |= GENERIC_READ; /* is this too little?
> > */
> > > > > -     if (OPEN_FMODE(oflags) & FMODE_WRITE)
> > > > > +             if (strstr(full_path, ":"))
> > > > > +                     desiredAccess |= FILE_READ_DATA | FILE_READ_EA
> > |
> > > > > +                             FILE_READ_ATTRIBUTES | READ_CONTROL;
> > > > > +     }
> > > > > +     if (OPEN_FMODE(oflags) & FMODE_WRITE) {
> > > > >               desiredAccess |= GENERIC_WRITE;
> > > > > +             if (strstr(full_path, ":"))
> > > > > +                     desiredAccess |= FILE_WRITE_DATA |
> > > > FILE_APPEND_DATA |
> > > > > +                                     FILE_WRITE_EA |
> > > > FILE_WRITE_ATTRIBUTES;
> > > > > +     }
> > > > >
> > > > >       disposition = FILE_OVERWRITE_IF;
> > > > >       if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
> > > > > diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> > > > > index 9154192..80f35f8 100644
> > > > > --- a/fs/cifs/file.c
> > > > > +++ b/fs/cifs/file.c
> > > > > @@ -43,22 +43,41 @@
> > > > >  #include "cifs_fs_sb.h"
> > > > >  #include "fscache.h"
> > > > >
> > > > > -static inline int cifs_convert_flags(unsigned int flags)
> > > > > -{
> > > > > -     if ((flags & O_ACCMODE) == O_RDONLY)
> > > > > -             return GENERIC_READ;
> > > > > -     else if ((flags & O_ACCMODE) == O_WRONLY)
> > > > > -             return GENERIC_WRITE;
> > > > > -     else if ((flags & O_ACCMODE) == O_RDWR) {
> > > > > +static inline int cifs_convert_flags(char *full_path, unsigned int
> > > > flags)
> > > > > +{
> > > > > +     int daccess = 0;
> > > > > +
> > > > > +     if ((flags & O_ACCMODE) == O_RDONLY) {
> > > > > +             daccess = GENERIC_READ;
> > > > > +             if (strstr(full_path, ":"))
> > > > > +                     daccess |= FILE_READ_DATA | FILE_READ_EA |
> > > > > +                             FILE_READ_ATTRIBUTES | READ_CONTROL;
> > > > > +             return daccess;
> > > > > +     } else if ((flags & O_ACCMODE) == O_WRONLY) {
> > > > > +             daccess = GENERIC_WRITE;
> > > > > +             if (strstr(full_path, ":"))
> > > > > +                     daccess |= FILE_WRITE_DATA | FILE_APPEND_DATA |
> > > > > +                             FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
> > > > > +             return daccess;
> > > > > +     } else if ((flags & O_ACCMODE) == O_RDWR) {
> > > > >               /* GENERIC_ALL is too much permission to request
> > > > >                  can cause unnecessary access denied on create */
> > > > >               /* return GENERIC_ALL; */
> > > > > -             return (GENERIC_READ | GENERIC_WRITE);
> > > > > +             daccess = GENERIC_READ | GENERIC_WRITE;
> > > > > +             if (strstr(full_path, ":"))
> > > > > +                     daccess |= FILE_READ_DATA | FILE_WRITE_DATA |
> > > > > +                             FILE_APPEND_DATA | FILE_READ_EA |
> > > > > +                             FILE_WRITE_EA | FILE_READ_ATTRIBUTES |
> > > > > +                             FILE_WRITE_ATTRIBUTES | READ_CONTROL;
> > > > > +             return daccess;
> > > >
> > > >
> > > > So if any component in the pathname happens to have a ':' in it, then
> > > > we'll open the file with a different set of access flags? ':' is a
> > > > perfectly legitimate character in posix pathnames. That sounds like a
> > > > very bad heuristic.
> > > >
> > > > >       }
> > > > >
> > > > > -     return (READ_CONTROL | FILE_WRITE_ATTRIBUTES |
> > > > FILE_READ_ATTRIBUTES |
> > > > > +     daccess = READ_CONTROL | FILE_WRITE_ATTRIBUTES |
> > > > FILE_READ_ATTRIBUTES |
> > > > >               FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
> > > > > -             FILE_READ_DATA);
> > > > > +             FILE_READ_DATA;
> > > > > +
> > > > > +     return daccess;
> > > > > +
> > > > >  }
> > > > >
> > > > >  static u32 cifs_posix_convert_flags(unsigned int flags)
> > > > > @@ -149,6 +168,8 @@ int cifs_posix_open(char *full_path, struct inode
> > > > **pinode,
> > > > >               goto posix_open_ret; /* caller does not need info */
> > > > >
> > > > >       cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
> > > > > +     if (strstr(full_path, ":"))
> > > > > +             fattr.cf_flags |= S_PRIVATE;
> > > > >
> > > > >       /* get new inode and set it up */
> > > > >       if (*pinode == NULL) {
> > > > > @@ -158,6 +179,8 @@ int cifs_posix_open(char *full_path, struct inode
> > > > **pinode,
> > > > >                       rc = -ENOMEM;
> > > > >                       goto posix_open_ret;
> > > > >               }
> > > > > +             if (strstr(full_path, ":"))
> > > > > +                     (*pinode)->i_flags |= S_PRIVATE;
> > > > >       } else {
> > > > >               cifs_fattr_to_inode(*pinode, &fattr);
> > > > >       }
> > > > > @@ -178,7 +201,7 @@ cifs_nt_open(char *full_path, struct inode
> > *inode,
> > > > struct cifs_sb_info *cifs_sb,
> > > > >       int create_options = CREATE_NOT_DIR;
> > > > >       FILE_ALL_INFO *buf;
> > > > >
> > > > > -     desiredAccess = cifs_convert_flags(f_flags);
> > > > > +     desiredAccess = cifs_convert_flags(full_path, f_flags);
> > > > >
> > > > >
> >  /*********************************************************************
> > > > >   *  open flag mapping table:
> > > > > @@ -538,7 +561,7 @@ static int cifs_reopen_file(struct cifsFileInfo
> > > > *pCifsFile, bool can_flush)
> > > > >                  in the reconnect path it is important to retry hard
> > */
> > > > >       }
> > > > >
> > > > > -     desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
> > > > > +     desiredAccess = cifs_convert_flags(full_path,
> > pCifsFile->f_flags);
> > > > >
> > > > >       if (backup_cred(cifs_sb))
> > > > >               create_options |= CREATE_OPEN_BACKUP_INTENT;
> > > > > diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> > > > > index 7354877..0bde128 100644
> > > > > --- a/fs/cifs/inode.c
> > > > > +++ b/fs/cifs/inode.c
> > > > > @@ -351,12 +351,17 @@ int cifs_get_inode_info_unix(struct inode
> > **pinode,
> > > > >                       cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
> > > > >       }
> > > > >
> > > > > +     if (strstr(full_path, ":"))
> > > > > +             fattr.cf_flags |= S_PRIVATE;
> > > > > +
> > > > >       if (*pinode == NULL) {
> > > > >               /* get new inode */
> > > > >               cifs_fill_uniqueid(sb, &fattr);
> > > > >               *pinode = cifs_iget(sb, &fattr);
> > > > >               if (!*pinode)
> > > > >                       rc = -ENOMEM;
> > > > > +             if (strstr(full_path, ":"))
> > > > > +                     (*pinode)->i_flags |= S_PRIVATE;
> > > > >       } else {
> > > > >               /* we already have inode, update it */
> > > > >               cifs_fattr_to_inode(*pinode, &fattr);
> > > > > @@ -713,10 +718,15 @@ cifs_get_inode_info(struct inode **inode, const
> > > > char *full_path,
> > > > >                       cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
> > > > >       }
> > > > >
> > > > > +     if (strstr(full_path, ":"))
> > > > > +             fattr.cf_flags |= S_PRIVATE;
> > > > > +
> > > > >       if (!*inode) {
> > > > >               *inode = cifs_iget(sb, &fattr);
> > > > >               if (!*inode)
> > > > >                       rc = -ENOMEM;
> > > > > +             if (strstr(full_path, ":"))
> > > > > +                     (*inode)->i_flags |= S_PRIVATE;
> > > > >       } else {
> > > > >               cifs_fattr_to_inode(*inode, &fattr);
> > > > >       }
> > > > > @@ -748,6 +758,10 @@ cifs_find_inode(struct inode *inode, void
> > *opaque)
> > > > >       if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
> > > > >               return 0;
> > > > >
> > > > > +     /* don't match inode with different flags */
> > > > > +     if ((inode->i_flags & S_PRIVATE) != (fattr->cf_flags &
> > S_PRIVATE))
> > > > > +             return 0;
> > > > > +
> > > > >       /* if it's not a directory or has no dentries, then flag it */
> > > > >       if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
> > > > >               fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
> > > >
> > > >
> > > > --
> > > > Jeff Layton <jlayton@xxxxxxxxx>
> > > >
> > >
> > > I think then this check for a : in the file name should be limited
> > > to non-posix_compliant cifs/smb servers like Windows?
> > > I do not think there is any way in the cifs protocol to ask whether
> > > a file object is an alternate data stream or not.
> > > A client should be oblivious to how and where a file object is
> > > stored as long as server honours its request.
> > >
> >
> > I think it's best to avoid "hidden" interfaces that change client
> > behavior based on the filename. If the only thing that's missing is to
> > request extra access flags, is there any reason not to request them
> > unconditionally?
> >
> > --
> > Jeff Layton <jlayton@xxxxxxxxx>
> >
> 
> Agree. There is no reason not to request these extra access flags
> unconditionally except that would be there be a case where access
> would be denied with the extra access flags which otherwise would
> be granted without extra access flags (i.e. with the current flag(s)).
> 
> At least in case of Windows servers, a regular file and alternate
> data stream have same file id.  So the only way to distinguish them
> is by a : in a file name.  I do not see any other way to distinguish
> them on the client.
> 

Can you clarify why extra access flags are needed in this case? What's
flags are missing and why are they needed?

-- 
Jeff Layton <jlayton@xxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux